2016-11-14 52 views
0

應該relativly簡單,但我不能算出它,我有以下幾點:如何將通用類型的項添加到列表中?

public static List<T> GetList <T>(dynamic data) 
    { 
     var lst = new List<T>(); 

     foreach (var d in data) 
     { 
      lst.Add(new T { Value = d.Id.ToString(), Text = d.Name };); 
     } 

     return lst; 
    } 

errror:

enter image description here

+0

爲什麼不使用接口? – JuanR

+1

你對'T'沒有限制。編譯器不知道'T'具有'Value'或'Text'屬性。 – Jonesopolis

+0

您將您的類型限制爲T,但不提供該類型的附加約束。編譯器無法知道是否存在屬性Value或Text。 – Igor

回答

7

您將您的類型限制爲T,但未爲該類型提供附加約束。編譯器無法知道是否存在屬性Value或Text。你可以使用一個接口,然後限制該類型。您在調用方法時傳入的類型也必須實現該接口。

public interface ITextValue{ 
    string Text {get;set;} 
    string Value {get;set;} 
} 

然後與制約因素

public static List<T> GetList <T>(dynamic data) where T : ITextValue, new() 
{ 
    var lst = new List<T>(); 

    foreach (var d in data) 
    { 
     lst.Add(new T { Value = d.Id.ToString(), Text = d.Name }); 
    } 

    return lst; 
} 

下面的代碼是可以適用於一般類型參數的約束上所有可用的約束和語法一個很好的鏈接。 Constraints on Type Parameters (C# Programming Guide)。並且@juan指出new()約束指定您使用的類型必須具有無參數構造函數。

+2

我剛剛學到了一些新的東西,謝謝,這個竅門 – ThunD3eR

+1

我想補充的一件事,我想@Igor忘了要提到的是new()約束。它告訴編譯器T有一個公共無參數的構造函數(這是什麼讓你做新的T {})。 – JuanR

+1

還有一件事。如果可能的話,我會避免使用動態,因爲它會跳過編譯時檢查。你可以讓傳遞給這個方法的類實現@Igor描述的接口。 – JuanR

0

需要約束到包含的價值和文本屬性的類或者它將無法找到這些屬性。例如:

其中TypeName是包含Value和Text的類型。

public static List<T> GetList <T>(dynamic data) where T : TypeName, new() 
    { 
    var lst = new List<T>(); 

    foreach (var d in data) 
    { 
     lst.Add(new T { Value = d.Id.ToString(), Text = d.Name };); 
    } 

    return lst; 
    } 
+4

這不起作用。它仍然會爆炸,因爲編譯器不知道T具有屬性Value和Text或者它們是什麼類型。 – JuanR

+0

是的,我剛剛意識到,並添加了一個註釋 – cstopher

+0

投票了編輯,這做了詭計以及 – ThunD3eR

1

對於C#泛型,只允許您對通用類型參數的實例執行這些操作,這些操作對於編譯器來說是已知的,以便存在於適合泛型類型約束的任何類型中,如通用類型或泛型方法。換句話說,在你的具體情況下,編譯器有兩個問題。

首先,您嘗試構建T的一個實例,但並非每種類型都可以像這樣構造(例如代表不能)。此外,不是每個可構造的類型是默認構造(換句話說有一個默認的構造函數)。爲了能夠構建這樣的類型T的實例,你需要需要噸至有一個默認的構造函數對T.

應用 新()約束

其次,要能夠初始化屬性文本在新構建的T實例上,您需要確保類型T指定了這些屬性,並且這些屬性是public可設置,通常通過強制T實現某個接口來完成。

這是你可能想在代碼中做什麼的一個小例子。

interface IHasStringValueAndText { 
    String Value { get; set; } 
    String Text { get; set; } 
} 

public static List<T> GetList<T>(dynamic data) where T : IHasStringValueAndText, new() { 
    var lst = new List<T>(); 

    foreach (var d in data) { 
     lst.Add(new T { Value = d.Id.ToString(), Text = d.Name }); 
    } 

    return lst; 
} 

請注意,如果你並不真正需要的約束爲您的特定情況下工作,但它可能對你今後的工作有用。

相關問題