什么是初始化属性
在声明属性的同时直接给属性进行初始化。
public IEnumerable<Score> MyScores { get; set; } = new HashSet<Score>();
若当一个类的属性是引用类型时,我们必须要先初始化该引用类型,才可以操作该类型。
比如:
public class User
{
public int Id { get; set; }
public ICollection<Score> Scores { get; set; }
}
public class Score
{
public int Mark { get; set; }
}
我有了两个类型,其中,User
类中有一个 Scores 属性是类 Score
导航属性。
当我们需要使用到 Scores
属性时,你可以有以下几种方式:
1、显示地手动实例化:
var user = new User();
user.Scores = new List<Score>(); //手动的 new 一次
user.Scores.Add(new Score { Mark = 100 });
当然,这样很麻烦,因为每一次都需要自己去实例化,保不齐忘记了就抛异常了。
2、在构造方法里实例化:
public User()
{
this.Scores = new HashSet<Score>();
}
因此,当我 new User()
时,就会执行构造方法,因此 Scores
也会跟着实例化了,所以我不用担心使用的时候有没有被实例化。这种方法应该被经常推荐使用
3、直接初始化属性
public ICollection<Score> Scores { get; set; } = new HashSet<Score>();
如果这样使用,就不需要在构造方法里再去实例化了,当然更方便。
那初始化属性和构造方法实例化的区别是什么?
既然构造方法里都能实例化了,那为什么还弄一个初始化属性呢?
这就需要去了解他们的执行顺序了。用简单的 debugger
来直观的表示。
public class User
{
public User()
{
this.Scores = new HashSet<Score>();
}
public int Id { get; set; }
public ICollection<Score> Scores { get; set; }
public IEnumerable<Score> MyScores { get; set; } = new HashSet<Score>();
}
改造一下这个 User
类,声明了两个属性都是 Score
类型的导航属性,一个用了构造方法去实例化,一个使用初始化属性来实例化。
然后我们开始调试:
首先进入了断点,因为还没有实例化 User
, 所以 user
对象是 null
;
然后按了 F11,进入逐步调试
你会惊奇地发现,程序先走了初始化属性这一步;
这个时候,才开始进入构造方法里,但是这时,初始化属性的 MyScores
对象已经可以被使用了,但由于构造方法还没有执行,因此 Scores
对象还是 null
;
当构造方法执行完毕,Scores
对象也被实例化。
因此我们得出了一个结论:初始化属性优先于构造方法
这都是一瞬间的事情,基本上没什么区别吧?
想一个场景,如果你需要在构造方法里做逻辑判断的时候,你就很有用了。
public User()
{
if (MyScores == null)
{
this.Scores = new HashSet<Score>();
}
}
当然,了解了执行顺序,就看你需要在什么样的场景去做使用。