在MSDN上面對new()解釋說到是where字句的構造函數約束,帶有new()約束的任何類型都必須有可訪問的無參構造函數,正常來說C#創建的類默認都有一個無參的構造函數,即使你沒有寫,但是如果你寫了一個有參數的構造函數后,那么就沒有默認無參的那個了,就需要自己手動寫一個。
還是拿前兩天的國籍那個舉個例子:
1
2
3
4
5
6
7
8
9
10
11
|
/// <summary>
/// 國籍的接口
/// </summary>
public interface INationality
{
string Nationality
{
set;
}
string GetNationality();
}
|
國籍的接口不用改變還是這個,繼承此接口的類稍微修改了一下,為每個類增加一個構造方法,改造如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
/// <summary>
/// 中國人
/// </summary>
public class Chinese : INationality
{
public Chinese(string DefaultNationality)
{
_Nationality = DefaultNationality;
}
private string _Nationality;
public string Nationality
{
set
{
_Nationality = value;
}
}
public string GetNationality()
{
return string.IsNullOrEmpty(_Nationality) ? "Chinese." : _Nationality;
}
}
/// <summary>
/// 美國人
/// </summary>
public class American : INationality
{
public American(string DefaultNationality)
{
_Nationality = DefaultNationality;
}
private string _Nationality;
public string Nationality
{
set { _Nationality = value; }
}
public string GetNationality()
{
return string.IsNullOrEmpty(_Nationality) ? "American." : _Nationality;
}
}
|
其實變動也不大,泛型類也沒有修改,但是會報錯,在創建實例化對象的地方,如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
public class PrintNationality<T> where T : INationality, new()//由於此處有new()的約束,所以編譯器編譯的時候無法通過,那么就將new()去掉,或者為繼承INationality的類增加public類型的無參構造函數
{
//T item = new T(); 在這個地方就不能創建實例化對象了,會提示錯誤“必須有具有公共無參構造函數的非抽象類型,才能用作泛型類型或方法"xxxx"中的參數T”
public void Print()
{
//Console.WriteLine(string.Format("Nationality:{0}", item.GetNationality()));
}
}
|
要解決上面的問題,就是給繼承INationality的接口的每個類都增加一個無參的public型的構造方法,或者,將派生類后面的new()去掉。這樣的話,當實例化泛型類的時候就不會有問題了。
上面寫那么多也是舉一個小例子,其實MSDN說的很明白,就是where字句后面有new()約束的話,T類型必須有公有的無參的構造函數。
又一篇相關文章:
對於new()約束,大家可能有一個誤解,以為使用了new約束之后,在創建對象時與非泛型的版本是一致的:
public class Tester<T> where T:new()
{
public Tester()
{
t = new T();//等同於非泛型版本的new? 例如 object o = new object();?
}
private T t;
}
事實上,使用new關鍵字的作用只是讓編譯器在泛型實例化之處,檢查所綁定的泛型參數T是否具有公共無參構造函數(public 無參構造函數):
Tester<SomeType> t = new Tester<SomeType>(); //此處編譯器會檢查SomeType是否具有無參構造函數。若沒有則會有compile error。
而Tester<T>類的構造函數中的new代碼,實際上等同於下面的代碼:
public class Tester<T> where T:new()
{
public Tester()
{
t = System.Activator.CreateInstance<T>();
}
private T t;
}
也就是說,仍然是用反射機制來獲取泛型對象的實例的。