2017-08-04 34 views
0

我發現此問題: Is it possible to specify a generic constraint for a type parameter to be convertible FROM another type? 我正在尋找更智能的方法。委託方法參數從IEnumerable <T>到特定類型

Class A { 
    public A(string){} 
} 

Class foo 
{ 
    private List<A> content = new List<A>(); 

    public void Add(A a){ 
     content.Add(a); 
    } 
    public void Add(string str){ 
     content.Add(new A(str)); 
    } 
    public void AddRange<T>(IEnumerable<T> iterable) // where T : ??? 
    { 
     foreach(T t in iterable) 
      content.Add((A)t); //Error 
    } 
} 

的錯誤是:

Cannot convert type 'T' to 'A'

問題:存在where T : ?表達,如 「可轉換」?

更新: 我有兩個方法超載: Add(A)Add(string) 目前我嘗試與T轉換爲A.但是我的主要問題是,我想使用不同Add與T. 方法我需要的是這樣的:

public void AddRange<T>(IEnumerable<T> iterable) where T : Add(T) 
{ 
    foreach (T t in iterable) 
     this.Add(t); 
} 
+7

目前尚不清楚您嘗試實現的目標。你不是隻是想'在哪裏T:A'? –

+0

這是什麼意思「可轉換」? –

+0

我想要添加兩種不同的枚舉類型:列表和列表。 – Syrlia

回答

3

我想你在找什麼約束鍵入必須有明確的運營商T,但由於規格說明:

conversion-operator-declarator: 
    implicit operator type ( type identifier ) 
    explicit operator type ( type identifier )

whi通常意味着你不能有通用的顯式和隱式操作符,我不認爲這是可能的。

你可以讓你的情況可能的,如果你有一些具體的類型然而,像這樣:

public class A 
{ 
    public static explicit operator B(A a) 
    { 
     return new B(); 
    } 
} 

public class B { } 

public class Convert 
{ 
    public static T To<T>(dynamic obj) 
    { 
     return (T) obj; 
    } 
} 

class Foo 
{ 
    private List<A> content = new List<A>(); 
    public void AddRange<T>(IEnumerable<T> iterable) where T : B 
    { 
     foreach (T t in iterable) 
      content.Add(Convert.To<A>(t)); // This will invoke the implicit operator defined in A 
    } 
} 

也許你可以抽象的通用T類型是B類型類型和約束它這樣,也許你定義類型T中所有希望轉換爲A的類型的隱式運算符。

1

如果你想T的類型爲A或任何派生類型使用where T : A

EDIT(您的評論後):

如果你想TAString你不能做這樣的事情:where T : A, String。您可以僅限制類,接口,類型,但不可能執行OR操作。

因此,在你的情況下,如果你只想要StringA那麼你應該使用不同的實現。如果你想要的任何類 - where T : class

+0

我得到這個錯誤:'字符串'不是一個有效的約束。用作約束的類型必須是接口,非密封類或類型參數。 – Syrlia

+0

@Syrlia,你什麼時候遇到這個錯誤?如果你試圖約束只接受'String',你將會失敗,因爲'String'是'sealed',並且不允許對'sealed'類的約束(沒有理由)。說不同的實現我的意思是兩個重載 - 如果你只需要兩種類型,你應該有兩個重載 - 在這種情況下,在泛型中是沒有必要的。 –

+0

另外兩個實現是沒有問題的,但是我想爲更大的案例學習它。這只是一個例子。 ;-) 我得到了錯誤,而改爲:'AddRange (IEnumerable iterable)其中T:A,字符串' – Syrlia

0

可以使用的,而不是T:

public void Add(IEnumerable<A> iterable) 
{ 
    foreach(A t in iterable) 
     content.Add(t); 
} 

和:

public void Add(IEnumerable<string> iterable) 
{ 
    foreach(string t in iterable) 
     content.Add(t); 
} 
+0

如果我嘗試調用AddRange(新列表()':「參數1:無法從'System.Collections.Generic.List '轉換爲System.Collections.Generic.IEnumerable '」 – Syrlia

+0

您必須添加兩個方法,因爲'string'不是一個有效的約束(對於where子句),因爲它是一個密封的類。 –