1、静态字段
静态字段用于多个实例共享的数据,类似全局变量,使用类名.成员名的形式来访问,看代码:
class Statistics
{
public static int _Count = 0;
public Statistics (int count)
{
_Count = _Count + count;
}
}
Statistics sta1 = new Statistics(1);
Statistics sta2 = new Statistics(1);
Console.WriteLine(Statistics._Count);
上述程序输出的 结果是2,因为静态变量被多个类的实例共享,所以每次实例化Statistics都会将静态字段_Count加上传入构造函数的值。
2、静态方法
当我们定义一个方法不需要访问任何实例数据时使用静态方法,否则使用实例方法。
1)
class Statistics
{
public static int _Count = 0;
public Statistics (int count)
{
_Count = _Count + count;
}
public static void ShowResult()//静态方法定义
{
Console.WriteLine("我是结果");
}
}
方法调用:
Statistics.ShowResult();
2)在静态方法中怎么去访问实例成员
class Statistics
{
public static int _Count = 0;
public Statistics(int count)
{
_Count = _Count + count;
}
public static void ShowResult()
{
Console.WriteLine("我是结果");
}
public static void AccessNoStaticData()//静态方法
{
TestNoStatic ts = new TestNoStatic();
ts.ShowData();
}
}
非静态类
class TestNoStatic
{
public void ShowData()//实例方法
{
Console.WriteLine("我是非静态成员");
}
}
调用静态方法
Statistics.AccessNoStaticData();
3、静态构造器
class Statistics
{
public static int _Count = 0;
static Statistics ()//静态构造器
{
_Count = 100;
}
public Statistics(int count)
{
_Count = _Count + count;
}
public static void ShowResult()
{
Console.WriteLine("我是结果");
}
public static void AccessNoStaticData()//静态方法
{
TestNoStatic ts = new TestNoStatic();
ts.ShowData();
}
}
Console.WriteLine(Statistics._Count);
输出结果为100,说明在访问静态字段_Count 时执行了静态构造函数,这个访问发生在静态字段_Count本省的初始化赋值之后,c#6.0本质论中指出,尽量不要使用静态构造器,而是直接考虑以内联的方式初始化静态字段,查阅了很多资料,都说在声明并对静态字段赋值就是以内联的方式初始化静态字段,如下,如有问题请指出:
class Statistics
{
public static int _Count = 0;//声明并赋值
public Statistics(int count)
{
_Count = count;
}
public static void ShowResult()
{
Console.WriteLine("我是结果");
}
public static void AccessNoStaticData()//静态方法
{
TestNoStatic ts = new TestNoStatic();
ts.ShowData();
}
}
4、静态属性
public static int Age { get; private set; } = 100;
尽量使用静态属性代替静态字段,毕竟静态属性还有一定程度的封装;
5、静态类
如果一个类完全没有实例成员,那么就将这个类声明成静态的,如下:
static class Statistics
{
public static int _Count = 0;//静态字段
public static int Age { get; private set; } = 100;//静态属性
public static void ShowResult()//静态方法
{
Console.WriteLine("我是结果");
}
public static void AccessNoStaticData()//静态方法
{
TestNoStatic ts = new TestNoStatic();
ts.ShowData();
}
}
静态类不可继承,无法实例化
6、扩展方法
public class TestNoStatic
{
public void ShowData()//实例方法
{
Console.WriteLine("我是非静态成员");
}
}
public static class TestExtendMethod//扩展方法所在的类的类型并不重要
{
public static void ExtendMethod(this TestNoStatic testNoStatic)//扩展方法
{
Console.WriteLine("我是扩展方法");
}
}
//调用:
TestNoStatic test = new TestNoStatic();
test.ExtendMethod();
扩展方法一般和接口配合使用,否则很少用它。
7、封装数据
主要是指两个字段修饰符,一个是const一个是readonly。
1)const
常量字段用于用于修饰恒定的量,比如圆周率,被const修饰的字段在程序中无法再被改变,如下:
private const double pi = Math.PI;
2)readonly
public class TestNoStatic
{
readonly int _Id=100;
public int Id
{
get
{
return _Id;
}
}
public TestNoStatic (int id)
{
this._Id = id;
}
public void ShowData()//实例方法
{
Console.WriteLine("我是非静态成员");
}
}
调用:
TestNoStatic test = new TestNoStatic(200);
Console.WriteLine(test.Id );
输出值为200,因为这个只读的字段只能从构造器中去修改。
注意:在c#6.0中其实不需要readonly修饰符,直接使用只读的自动实现的属性就好。
如下:
public string Name { get; } = “小王”;
注意:对于属性数组,有如下特性,对于数组类型的属性而言,系统认为对属性的赋值是改变数组的个数而不是改变数组中元素的值。
public bool[] cell { get; } = new bool[2];
cell[0] = false;//可以赋值
cell[1] = false;//可以赋值
cell = new bool[3];//不可以赋值
8、嵌套类
public class TestNoStatic
{
public void ShowMethod()//实例方法
{
Inner inner = new Inner();
inner.ShowMethod();
}
private class Inner//嵌套类
{
public void ShowMethod()
{
Console.WriteLine("我是嵌套类中的方法");
}
}
}
调用
TestNoStatic test = new TestNoStatic();
test.ShowMethod();
我们可以看到嵌套类Inner的访问修饰符是private,在命名空间下的类的访问修饰符不能声明为private,也只有在是嵌套类的时候才可以,将嵌套类声明为private,这样就避免了被别的类访问,我们声明嵌套类的时候也是因为这个类声明在它的包容类外面没有意义的时候才将它声明为嵌套类,并且有以下几个特点:
1)避免将嵌套类声明为public;
2)嵌套类中的this代表嵌套类而不是包容类的实例;
3)嵌套类能访问包容类中任何成员,包括私有成员;
4)包容类不能访问嵌套类的私有成员;
但是如果碰到了嵌套类声明为public的情况,我们使用方式如下:
public class TestNoStatic
{
public void ShowMethod()//实例方法
{
Inner inner = new Inner();
inner.ShowMethod();
}
public class Inner//嵌套类
{
public void ShowMethod()
{
Console.WriteLine("我是嵌套类中的方法");
}
}
}
这里注意我们不能直接写成如下形式,会报错:
Inner inner = new Inner();//报错,也就是说Inner即使声明为pulic也是直接访问不了的,必须用如下形式:
TestNoStatic.Inner inner = new TestNoStatic.Inner();
inner.ShowMethod();
9、分部类和分部方法
partial class PartA
{
public void GetValue()//分部类中方法1
{
Console.WriteLine("我是文件一");
}
partial void ShowPart();//分部方法不能有访问修饰符,这是在一个类中定义分部方法
}
partial class PartA
{
public void GetValue2()//分部类中方法2
{
Console.WriteLine("我是文件二");
ShowPart();
}
partial void ShowPart()//在另一个类中实现分部方法。
{
Console.WriteLine("我是分部方法");
}
}
1)分部类用partial 修饰;
2)分部方法在分部类中;
3)分部方法不能使用访问修饰符,默认private或者protect,有待验证;
4)分部方法在使用时一个类中声明,另一个类中实现,当然也可以只声明但是不实现,如果不实现,但是方法也被调用了,但是程序不会报错,程序选择了直接跳过这段代码。