简体   繁体   中英

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

Let's say I have an method:

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

InputSource is my own generic class. Ideally, I want the List to be a list of InputSources of any instance of the generic. Is this doable? In other words, I want inputs to be able to hold an InputSource<double> , an InputSource<string> , and an InputSource<int> all in the same instance.

I tried this, but then I tried to use the method:

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);

The labeled line gives me a compiletime error:

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

Trying to add an explicit cast:

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

gives the following error:

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

What is the correct way to achieve my goal here?

Maybe you can change your code like this,all InputSource based on IInputSource

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

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

Change the signature of the update() method using generics with some constraints

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

// Check the T for safe if you want

Your compile error is not related to the update() method, there is error when you call the Add() method:

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

Even casting a InputSource<double> to InputSource<dynamic> is illegal, no matter InputSource is covariant or contravariant, because these variance does not apply to value type (for someone interested, you may try to compile IEnumerable<object> objs = new List<double>() ):

InputSource<dynamic> ipDynamic = ipDouble; // illegal

You may use List<dynamic> or List<object> instead of List<InputSource<dynamic>> for storing a list of different objects.

Here is a variation of Sky Fang's answer that you might like better. Use an abstract class InputSource instead of IInputSource and derive InputSource from that. Then you can do something like the following:

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>());
}

With an interface, everything is public. With the abstract class, you can define protected abstract methods and properties, that you override in the generic subclass. You can create methods that are not type safe in the abstract class, and then hide them with type safe equivalents in the generic subclass (like the GetValue method in this example).

And if you still want to use the IInputSource interface, you can have the abstract class implement that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM