在使用动态的方法中获取任意泛型列表

Taking in a list of arbitrary generics in a method using dynamic

假设我有一个方法:

public void update(List<InputSource<dynamic>> inputs);

InputSource 是我自己的通用 class。理想情况下,我希望 List 是任何泛型实例的 InputSources 列表。这可行吗?换句话说,我希望输入能够在同一实例中包含 InputSource<double>InputSource<string>InputSource<int>

我试过这个,但后来我尝试使用方法:

InputSource<double> ip = new InputSource<double>();

List<InputSource<dynamic>> inputSources = new List<InputSource<dynamic>>(){ip}; //THIS LINE GIVES ME A COMPILE TIME ERROR

update(inputSources);

标记的行给我一个编译时错误:

Error   6   The best overloaded Add method 'System.Collections.Generic.List<InputSource<dynamic>>.Add(InputSource<dynamic>)' for the collection initializer has some invalid arguments  
Cannot convert from 'InputSource<double>' to 'InputSource<dynamic>' 

正在尝试添加显式转换:

List<InputSource<dynamic>> inputSources = new List<InputSource<dynamic>>(){(InputSource<dynamic>)inputSource};

给出以下错误:

Error   6   Cannot convert type 'InputSource<double>' to 'InputSource<dynamic>'

在这里实现我的目标的正确方法是什么?

也许你可以像这样更改你的代码,所有InputSource基于IInputSource

public interface IInputSource
{ 
}
public class InputSource<T> : IInputSource
{
}

public void update(IList<IInputSource> inputs)
{
    IInputSource ip = new InputSource<double>();
    inputs.Add(ip);
}

使用具有某些约束的泛型更改 update() 方法的签名

public void update<T>(List<InputSource<T>> inputs) where T: 
    IComparable,
    IComparable<T>,
    IConvertible,
    IEquatable<T>

// Check the T for safe if you want

你的编译错误与update()方法无关,调用Add()方法时出现错误:

List<InputSource<dynamic>> inputSourceList = new List<InputSource<dynamic>>();
InputSource<double> ipDouble = new InputSource<double>();
inputSourceList.Add(ipDouble); // illegal

即使将 InputSource<double> 转换为 InputSource<dynamic> 也是非法的,无论 InputSource 是协变还是逆变,因为这些变化不适用于值类型(有兴趣的人可以尝试编译 IEnumerable<object> objs = new List<double>()):

InputSource<dynamic> ipDynamic = ipDouble; // illegal

您可以使用 List<dynamic>List<object> 而不是 List<InputSource<dynamic>> 来存储不同对象的列表。

以下是 Sky Fang 答案的变体,您可能会更喜欢。使用抽象 class InputSource 而不是 IInputSource 并从中派生 InputSource。然后您可以执行以下操作:

public
abstract    class   InputSource
{ 

    public      InputSource<T>  As<T>()     { return (InputSource<T>) this; }

    protected
    abstract    Object          getValue();

    public      Object          GetValue()  { return this.getValue(); }

}

public      class   InputSource<T> : InputSource
{

    public
    override    object  getValue()  { return this.GetValue(); }

    public
    new         T       GetValue()  { /* todo: do something interesting here */ throw new NotImplementedException(); }

}

public void update(IList<InputSource> inputs)
{
    inputs.Add(new InputSource<double>());
    inputs.Add(new InputSource<int>());
}

有了界面,一切都是public。使用抽象 class,您可以定义受保护的抽象方法和属性,您可以在通用子 class 中覆盖它们。您可以在抽象 class 中创建类型不安全的方法,然后在通用 subclass 中使用类型安全的等价物隐藏它们(如本例中的 GetValue 方法)。

如果您仍想使用 IInputSource 接口,可以让抽象 class 实现它。