在dotnet 3.0后提供了自动属性和初始化器的功能。
自动属性如下2-4行,为什么如此简洁,据了解是因为C#编译器遇上象上面这样的空的get/set属性的话,它会自动为我们在类中生成一个私有成员变量,对这个变量实现一个公开的getter 和setter。
初始化器如下第5行,即可以通过属性或则声明为public的成员变量来初始化一个类。
View Code
1 publicclass Person {
2 publicstring FirstName { get; set; }
3 publicstring LastName { get; set; }
4 publicint Age { get; set; }
5 Person person =new Person { FirstName="Scott", LastName="Guthrie", Age=32 };
6 }
这些确实带来了一些便利之处。
当我们为这些新特性带来的便利感到兴奋时,这其中隐含的陷阱也就悄然浮现。
那么,'初始化器'new出来的类也应该与'构造函数'new出来的类同等吧,事实却泼了我一盆冷水。
初始化器与构造函数在初始化类时所达到的效果并不完全相同。
请看代码:
publicclass FileInfo
{
publicstaticevent EventHandler<ProgressValueArgs> OnProgressValueChanged;
privatelong offset;
public FileInfo()
{
}
public FileInfo(long offset, long size)
{
this.offset = offset;
this.Size = size;
}
publiclong Offset
{
get
{
return offset;
}
set
{
//当offset被赋值时将会引发事件,事件将会把该类本身作为参数传递给事件的接收者
if (null!= OnProgressValueChanged)
OnProgressValueChanged(this, new ProgressValueArgs(this));
offset = value;
}
}
publiclong Size
{
get;
set;
}
}
当分别使用对象初始化器赋值方式一、二,结果却不同
1 public class Class1{
2
3 public Class1
4 {
5 //对象初始化器赋值方式一
6 FileInfo fileinfo =new FileInfo(){Offset=-1,Size=-2};
7 //对象初始化器赋值方式二
8 fileinfo = new FileInfo(){Size=-2,Offset=-1};
9 FileInfo.OnProgressValueChanged +=new EventHandler<ProgressValueArgs>(Download_OnProgressValueChanged);
10 }
11
12 privatevoid Download_OnProgressValueChanged(object sender, ProgressValueArgs e)
13 {
14 System.Console.WriteLine(String.Format("OFFSET:{0}大小{1}", e.FileInfo.Id, e.FileInfo.Offset, e.FileInfo.Size));
15 }
16 }
上述情况的原因很简单 ,第一种赋值方式中,事件是在Offset被赋值后就发生了,并在Size被赋值前事件就已经结束。第二种赋值方式中,事件是在Size,Offset都赋值后才发生的,所以产生的结果也就不同。
正确的代码如下:
publicclass FileInfo
{
publicstaticevent EventHandler<ProgressValueArgs> OnProgressValueChanged;
privatelong offset;
public FileInfo()
{
}
public FileInfo(long offset, long size)
{
this.offset = offset;
this.Size = size;
}
publiclong Offset
{
get
{
return offset;
}
set
{
//当offset被赋值时将会引发事件,事件将会把该类本身作为参数传递给事件的接收者
if ( null!= OnProgressValueChanged && true == isSizeChanged ){
OnProgressValueChanged(this, new ProgressValueArgs(this));
isSizeChanged = false;
}
offset = value;
}
}
private long size;
private bool isSizeChanged;
publiclong Size
{
get{return size;}
set{
size = value;
isSizeChanged = true;
}
}
}
也就是为事件所依赖的其余变量设立一个标志,这些标志应该作为事件是否被引发的条件。