将 IEnumerable<T> 中的方法参数委托给特定类型

Delegate Method parameter from IEnumerable<T> to specific type

我发现了这个问题: Is it possible to specify a generic constraint for a type parameter to be convertible FROM another type? 我正在寻找更聪明的方法。

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 : ?表达式,如"convertable"?

更新: 我有两个方法重载: Add(A)Add(string) 目前我尝试将 T 转换为 A。但我的主要问题是,我想使用与 T 相关的不同 Add 方法。 我需要的是:

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

如果您希望 T 成为类型 A 或任何派生类型,请使用 where T : A.

编辑(在您发表评论后):

如果您希望 T 成为 AString,您不能这样做:where T : A, String。只能约束class、接口、类型,不能OR操作

因此,在您的情况下,如果您只需要 StringA,那么您应该使用不同的实现。如果你想要任何 class - where T : class

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

我认为您正在寻找必须具有显式运算符 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 类型并像那样对其进行约束,或者您可以定义所有类型的隐式运算符,这些运算符希望您转换为 A输入 T。