8

Is it possible to add different type of generic objects to a list?. As below.

public class ValuePair<T>
{        
    public string Name { get; set;}
    public T Value { get; set;                     
}

and let say I have all these objects...

 ValuePair<string> data1 =  new ValuePair<string>();
 ValuePair<double> data2 =  new ValuePair<double>();
 ValuePair<int> data3 =  new ValuePair<int>();

I would like to hold these objects in a generic list.such as

List<ValuePair> list = new List<ValuePair>();

list.Add(data1);
list.Add(data2);
list.Add(data3);

Is it possible?

1

4 Answers 4

13

In general, you'd have to either use a List<object> or create a non-generic base class, e.g.

public abstract class ValuePair
{
    public string Name { get; set;}
    public abstract object RawValue { get; }
}

public class ValuePair<T> : ValuePair
{
    public T Value { get; set; }              
    public object RawValue { get { return Value; } }
}

Then you can have a List<ValuePair>.

Now, there is one exception to this: covariant/contravariant types in C# 4. For example, you can write:

var streamSequenceList = new List<IEnumerable<Stream>>();

IEnumerable<MemoryStream> memoryStreams = null; // For simplicity
IEnumerable<NetworkStream> networkStreams = null; // For simplicity
IEnumerable<Stream> streams = null; // For simplicity

streamSequenceList.Add(memoryStreams);
streamSequenceList.Add(networkStreams);
streamSequenceList.Add(streams);

This isn't applicable in your case because:

  • You're using a generic class, not an interface
  • You couldn't change it into a generic covariant interface because you've got T going "in" and "out" of the API
  • You're using value types as type arguments, and those don't work with generic variable (so an IEnumerable<int> isn't an IEnumerable<object>)
Sign up to request clarification or add additional context in comments.

Comments

5

Not unless you have a non-generic base-type ValuePair with ValuePair<T> : ValuePair (it would work for an interface too), or use List<object>. Actually, though, this works reasonably:

public abstract class ValuePair
{
    public string Name { get; set; }
    public object Value
    {
        get { return GetValue(); }
        set { SetValue(value); }
    }
    protected abstract object GetValue();
    protected abstract void SetValue(object value);
}
public class ValuePair<T> : ValuePair
{
    protected override object GetValue() { return Value; }
    protected override void SetValue(object value) { Value = (T)value; }
    public new T Value { get; set; }
}

Comments

1

No, it is not possible. You could create, in your case, a base class ValuePair from which ValuePair<T> derives. Depends on your purposes.

Comments

1

it's not possible as far as I know.

the line:

List<ValuePair> list = new List<ValuePair>();

you wrote in your sample is not providing a concrete type for T and this is the issue, once you pass it, you can only add object of that specific type.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.