Delegate Method parameter from IEnumerable<t> to specific type

时间:2017-08-04 13:11:22

标签: c# generics ienumerable

I found this question: Is it possible to specify a generic constraint for a type parameter to be convertible FROM another type? I am looking for a smarter way.

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
    }
}

The Error is:

Cannot convert type 'T' to 'A'

Question: Exists a where T : ? expression like "convertable"?

Update: I have two method overloadings: Add(A)and Add(string) Currently i try to convert T to A. But my main problem is, that i want to use different Addmethods relating to T. What i need is something like:

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

3 个答案:

答案 0 :(得分:3)

我认为您要查找的约束类型必须具有显式运算符T,但由于规范说明:

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

这通常意味着你不能使用通用的显式和隐式算子,我不认为这是可能的。

如果你有一些具体的类型,你可以使你的情况成为可能:

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 :(得分:1)

If you want T to be the type A or any derived type use where T : A.

EDIT(after your comment):

If you want T to be A or String you can't do something like this: where T : A, String. You can constraint only class, interface, type, but it is not possible to do OR operation.

So, in your case if you want only String or A then you should use different implementations. If you want any class - where T : class

答案 2 :(得分:0)

您可以使用A代替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);
}