您的位置:首页 > 编程语言 > C#

【c#】定义类成员(字段、方法、属性)

2017-07-16 22:15 302 查看
成员定义

public----成员可以由任何代码访问
private----成员只能由类中的代码访问(如果没有使用任何关键字,默认使用这个关键字)
internal----成员定只能由义他的程序集(命名空间)内部的代码访问
protected----成员只能由类或派生类的代码访问
protect和internal也可以结合使用 protected internal ,表示它们只能由项目中派生类的代码来访问
用static关键字修饰,则表示它们是类的静态成员,而不是对象的实例成员

1.字段的定义
标准的变量声明格式

class MyClass
{
public int MyInt;
}

readonly 关键字

表示这个字段只能在 执行构造函数的过程中赋值,或者由初始化语句赋值

初始化时赋值

class MyClass
{
public readonly int MyInt = 2017;
}

static 关键字,将字段声明为静态

class MyClass
{
public static int MyInt;
}

注意:静态字段必须通过定义他们的类来访问,不能通过实例化的对象来访问

上面的示例中,只能这样访问

MyClass.MyInt

const 关键字,可以用 const 关键字定义一个常量,其也是静态的,但是不能用 static修饰,否则会出错

2.定义方法
标准函数格式、可访问性和可选的 static 修饰符来声明

注意:用static修饰后,只能通过类访问,不能通过实例化的对象访问

使用关键字

virtual----方法可以重写
abstract----方法必须在非抽象的派生类中重写(只用于抽象类)
override----方法重写了一个基类方法(要重写方法,必须用这个关键字)
extern----方法定义在其他地方

注意:
如果使用了override,也可以使用 sealed 来指定 派生类中不能对这个方法进一步修改
3.定义属性
属性是一种类的成员,它的实现类似函数,访问类似字段
作用是提供一种灵活和安全的机制来访问、修改私有字段
属性必须依赖于字段

属性拥有两个类似于函数的块,set 和 get ,set 设置属性的值,get 获取属性的值

private int myInt;

public int MyInt
{
get{ return myInt * 3;}
set{ myInt = value / 3;}
}

这两个块称为 访问器,可以用来控制属性的访问级别
可以忽略其中的一个块创建只读或只写属性 (没有set的属性是一种只读属性,没有get的访问器是一种只写属性)

注意:这里的只读和只写只适用于外部代码,类中的其他代码依旧能访问其中的数据

get访问器用来返回字段或者计算 并返回字段,它必须以return或者throw终结
set访问器类似返回类型为void的函数,使用value的隐式参数

注意:value 关键字表示用户提供的属性值,其类型和属性相同,所以如果属性和字段使用相同的类型,就不用类型转换。

//类中MyClass
private int myInt;

public int MyInt
{
get{ return myInt;}
set
{
if(value >= 0 && value <= 10)
myInt = value;
}
}

//类外使用
MyClass myObj = new MyClass();

for(int i = -1; i < 1; i++)
{
myObj.MyInt = i;
}

上述代码中,如果赋给属性的值不满足 value >= 0 || value <= 10,也就是说使用了无效的值,该怎么办?

什么也不做,如上述代码
给字段赋默认值
继续执行,就像没发生错误一样,但是记录下该事件,以备将来分析
抛出异常

一般情况下,后两种处理方式较好,使用 4 的方法,代码如下

set
{
if (value >= 0 && value <= 10)
{
myInt = value;
}
else
{
throw (new ArgumentOutOfRangeException("MyIntProp", value,
"MyIntProp must be assigned a value between 0 and 10"));
}
}

属性访问标记可以为public,private,protected,internal,protected internal
因为访问器的访问限制必须比属性的访问限制更加严格,所以

不能对接口或者显式的接口使用访问修饰符,因为接口里里面所有的默认是public的
同时具有get,set访问器时,才允许使用访问修饰符,并且只能有一个使用
如果属性有override修饰的时候,访问器修饰符必须与被重写的匹配
访问器的可访问级别必须比属性的可访问级别更加严格

private int myInt;
public int MyInt
{
public get { return myInt; } //error 因为访问器的级别和属性相同,所以错误(访问器访问级别更加严格)
set { myInt = value; }
}

理解:
首先第四条最容易想到,也是很合理的,毕竟是外围的决定内部的。
其次,既然第四条可以理解,那么如果只有一个访问器的时候,访问器访问级别等同属性,如果这个时候再去指 定更加严格的访问级别,那么为何不当初在属性上指定呢?
这条理解了,那么为什么必须同时具有get,set才能添加访问修饰符就更加明确了。

推理:
接口中属性是public的,那么如果接口中只有一个get或者set的时候,我们可以在继承中指明另一个访问器的属性。(接口中只有一个访问器,另一个可以在继承中指明访问级别)
但是如果接口中同时具有get,set,那么按照派生和继承的匹配性,这时候就不能这样再指定访问器的访问限制了。 (接口中有两个访问器,不能再指定访问器的访问级别)

public interface ISomeInterface
{
int TestProperty
{
// No access modifier allowed here
// because this is an interface.
get;
}
}

public class TestClass : ISomeInterface
{
public int TestProperty
{
// Cannot use access modifier here because
// this is an interface implementation.
get { return 10; }

// Interface property does not have set accessor,
// so access modifier is allowed.
protected set { }
}
}

可以用static 修饰属性,以便随时访问

private static int counter;
public static int Counter
{
get { return counter; }
}

属性隐藏

public class Employee
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}

public class Manager : Employee
{
private string name;

// Notice the use of the new modifier:
public new string Name // use new to hide property in base class
{
get { return name; }
set { name = value + ", Manager"; }
}
}

virtual来修饰属性,派生类使用override来重写属性

public class Parent
{
public virtual int TestProperty
{

protected set { }
get { return 0; }
}
}
public class Kid : Parent
{
public override int TestProperty
{
protected set { }
get { return 0; }
}
}

abstract 修饰属性,派生类来实现属性

abstract class Shape
{
public abstract double Area
{
get;
set;
}
}

class Square : Shape
{
public double side;
public override double Area
{
get
{
return side * side;
}
set
{
side = System.Math.Sqrt(value);
}
}
}

sealed 修饰属性,派生类不能修改属性

接口属性

接口属性不具有函数体

自动属性

当属性访问器中不需要其他访问逻辑时候,就可以使用自动属性,使代码更加简洁

public double TotalPurchases { get; set; }

有两个使用场景:

在接口中定义,继承接口的类就可以用了。
当有个字段不需要限制访问,为了编程习惯又不想写成公有字段,同时有懒得主动写那个字段名的时候,就使用自动属性吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: