2017-08-04 73 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子句),因为它是一个密封的类。 –