04.C#开发实战1200例笔记-编程基础篇:面向对象

面向对象

C#开发实战1200例第一卷有888页,这篇文章覆盖131-162页。

1 属性

可以添加对数据访问的限制。添加属性的快捷方式: 字段处-右键-重构-封装字段(Ctrl+R Ctrl+E)。set访问器存在隐式参数value,所以set中不能自定义名称为value。
【修饰符】【类型】【属性名】
{
get{get访问器体}
set{set访问器体}
}

    private string id2 = "";
    public string Id2
    {
        get { return id2; }
        set { id2 = value; }
    }

2 方法

2.1 访问修饰符

  • private:声明他们的类和结构体中才可访问。
  • public :没有限制。
  • protected :在声明他们的类中可访问并且可有派生类访问。
  • internal:在同一程序集的文件中,内部类型或成员才可访问。

2.2 声明修饰符

  • partial :在同一程序集中定义分部类和结构。
  • new:在用作修饰符时, new 关键字可以显式隐藏从基类继承的成员。 隐藏继承的成员时,该成员的派生版本将替换基类版本。虽然可以在不使用 new 修饰符的情况下隐藏成员,但会生成警告。
  • static:声明属于类本身的成员而不是属于特定对象的成员。
  • virtual :在派生类中可重写成员方法或访问器。虚方法可以在派生类中override但不强制。
  • override :提供从基类继承的虚拟成员的新实现。
  • sealed :指定类不能被继承。
  • abstract :指示某个类只能是其它类的基类。
  • extern:指示在外部实现方法。
partial class ClsBase
    {
       [DllImportAttribute("Kernel32.dll")]
        public static extern void GetLocalTime(SystemTime st);//static extern 
    }
    public abstract partial class ClsBase //partial同一程序集中定义分部类和结构
    {
        protected abstract int sub(int a, int b);
        protected int Add(int a,int b)
        {
            return a + b;
        }
    }

    public sealed class ClsChild:ClsBase
    {
        protected new int Add(int a, int b)//new 隐藏从基类继承的成员
        {
            return a + b;
        }
        protected override int sub(int a, int b)//override 重写基类虚拟方法sub(int a, int b)
        {
            return a + b;
        }
    }

2.3 重载

方法名称相同,参数数据类型、个数或顺序不同的方法。方法签名,就是方法的名称和每一个形参的类型和种类(值、引用、或输出)组成的。方法签名不区分ref和out参数。
除了类以外,重载也可以出现在接口或者结构中。
除了方法外,也可以对构造函数索引器及运算符等进行重载。

3 结构

为结构分配数据时不需要从托管堆中分配内存,结构中可以包括构造函数、常量、字段、方法、属性、运算符、事件、嵌套类型等,但如果同时包括以上几种成员,则应该考虑使用类。使用结构对于小的数据结构特别有用,能够节省大量的分配内存。
结构的特点:

  • 结构是值类型。
  • 向方法中传递结构时,是通过传值方式传递的,而不是作为引用传递的。
  • 结构的实例化可以不使用new运算符。
  • 结构可以声明构造函数,但它们必须带参数。
  • 一个结构不能从另一个结构或类继承。所有结构都直接继承自System.ValueType,而System.ValueType继承自System.Object。
  • 结构可以实现接口。
  • 在结构中初始化实例字段是错误的。
  • 结构的副本由编译器自动创建和销毁,因此不需使用默认构造函数和析构函数。实际上,编译器通过为所有字段赋予默认值来实现默认构造函数。
    结构格式:
    【结构修饰符】 struct 【结构名】
    {
    }
public struct Rect//定义一个矩形结构 结构是在栈上分配数据
{
    public double width;//矩形的宽
    public double height;//矩形的高 
    public Rect(double x, double y)
    {
        width = x;
        height = y;
    }
    public double Area()
    {
        return width * height;
    }
} 
private void button1_Click(object sender, EventArgs e)
{
    Rect myRect = new Rect(3,2);
    Rect myRect1;
    myRect1.width = 20;
    myRect1.height = 32; 
    double area = myRect.Area();
}

4 类和接口

面向对象编程技术:OOP
继承:只支持单继承。基类的成员可以是虚拟的。
抽象类和接口的区别:

  • 派生类只能继承一个基类,只能继承一个抽象类,但可以继承任意多个接口。
  • 抽象类中可以定义成员的实现,但接口中不可以。
  • 抽象类中可以包含字段、构造函数、析构函数、静态成员或常量,接口中不可以。
  • 抽象类中的成员可以是私有的(不能是抽象的)、受保护的、内部的、或保护的内部成员,但接口中的成员必须是公共的。
    接口
    描述可属于任何类或结构的一组相关行为,可以把它看成是实现一组类的模板。接口可由方法、属性、事件和索引器构成,但不能包含字段。
    类和结构可以从接口继承,若要实现接口成员,类或结构中的对应成员必须是公共的、非静态的。并且与接口成员有相同的名称和签名。
    接口的特征:
  • 接口类似于抽象基类,继承接口的任何非抽象类型都必须实现接口的所有成员。
  • 不能直接实例化接口。但是接口可以通过继承类实例化。
  • 接口可以包含事件、索引器、方法和属性。
  • 接口不包含方法的实现。
  • 类、结构、接口可从多个接口继承。
interface ISelectLanguage
{
    void Speak(string str);
} 
class C_SpeakEnglish : ISelectLanguage
{
    public void Speak(string str)
    {
        MessageBox.Show("您对美国友人说:" +str, "提示");
    }
} 
private void button1_Click(object sender, EventArgs e)
{
    ISelectLanguage Interface1 = new C_SpeakEnglish();//接口可以通过继承类实例化
    Interface1.Speak("hello"); 
}

5 迭代器

迭代器是.net3.5中的一个新特性,可以返回相同类型的值的有序序列的一段代码。
IEnumerable接口包含IEnumerator<T> GetEnumerator()方法。IEnumerator
接口访问集合中的项,有Current属性、MoveNext()、Reset()。迭代器可以用作方法、运算符或get访问器的代码体。
在迭代器中,通常使用yield return语句依次返回每个元素,使用yield break语句终止迭代。返回类型必须是IEnumerator或Enumerable。

public static IList<object> items = new List<object>();
public static IEnumerable<object> GetValues()
{
    if (items != null)//如果泛型不为空
    {
        foreach (object i in items)//遍历泛型中的对象
            yield return i;
    }
}
private void Form1_Load(object sender, EventArgs e)
{
    //向泛型集合中添加站点数据
    items.Add("长新东路");
    items.Add("同康路"); 
    items.Add("公平路");
    items.Add(108);
    items.Add(true);
}
private void button1_Click(object sender, EventArgs e)
{
    foreach (object i in GetValues())//遍历泛型集合
        listView1.Items.Add(i.ToString());//在列表视图中显示公交车站点
}

6 泛型

利用参数化类型将类型抽象化。具备可重用性、类型安全和效率高等特性。C#反省类型替换是在运行时执行的。
语法格式如下:

【类修饰符】class 【类名】<类型参数 T>
{
}
【修饰符】【返回值类型】【方法名】<类型参数 T>()
{
}

T是一个占位符,不是类型,仅代表了某种可能的类型。.net类库中提供的泛型类,主要有Dictionary<TKey,TValue>、List<T>、Queue<T>、Stack<T>、SortedList<TKey,TValue>等,都位于System.Collections.Generic中。

public int find<T>(T[] items, T item)
{
    for (int i = 0; i < items.Length; i++)
    {
        if (items[i].Equals(item))
        {
            return i;
        }
    }
    return -1; 
} 

7 Equals方法***

C# 等同性:

  • 逻辑等同性:两个对象在逻辑上代表同样的值。
  • 引用等同性:两个引用指向同一个对象实例。

Object.Equals()可以用来确定两个对象的引用等同性。而Object的派生类ValueTpye重写了Equals方法,比较的是逻辑等同性。引用类型Equals方法的默认实现来自Object,而值类型的默认实现来自TypeValue,也就是说,在C#里,引用类型关注的是引用等同性,而值类型关注的是逻辑等同性。
对于引用类型,Equals的默认实现很简单,仅仅需要判断两个引用是不是同一种类型、两个引用指向的是不是同一块内存就可以了。所以其性能也没有问题。但是对于值类型,Equals的任务就没有这么简单了。它需要对两个对象的所有字段都做出比较,即逐字段调用字段类型的Equals。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值