在使用动态的方法中获取任意泛型列表
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 实现它。
假设我有一个方法:
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 实现它。