问题
If I have a generic interface with a couple of implementing classes such as:
public interface IDataElement<T>
{
int DataElement { get; set; }
T Value { get; set; }
}
public class IntegerDataElement : IDataElement<int>
{
public int DataElement { get; set; }
public int Value { get; set; }
}
public class StringDataElement : IDataElement<String>
{
public int DataElement { get; set; }
public String Value { get; set; }
}
Is it possible to pass a collection of the implementing classes of differing types, without having to resort to passing as object.
It does not appear to be possible to define a return values as
public IDataElement<T>[] GetData()
or
public IDataElement<object>[] GetData()
Any suggestions?
回答1:
You can certainly declare:
public IDataElement<T>[] GetData<T>()
and
public IDataElement<object>[] GetData()
although the latter probably isn't what you're after (your interface won't be variant even in C# 4 as it uses
Tin both an input and an output position; even if it were variant, you wouldn't be able to use that variance for value types). The former will require the caller to specify<T>, e.g.foo.GetData<string>();
Is that okay for you?
There's no way of expressing "a collection of object, each of which implements IDataElement<T> for a different T" unless you also give it a nongeneric base class, at which you could just use IList<IDataElement>. In this case the nongeneric IDataElement could have the DataElement property, leaving the Value property in the generic interface:
public interface IDataElement
{
int DataElement { get; set; }
}
public interface IDataElement<T> : IDataElement
{
T Value { get; set; }
}
Is that useful in your particular situation?
It's not clear how you'd want to use a collection of data elements without knowing their types... if the above doesn't help you, maybe you could say more about what you expected to do with the collections.
回答2:
No you can't do this - the only options are to either use a non-generic interface:
public interface IDataElement
{
int DataElement { get; set; }
object Value { get; set; }
}
Alternatively create a wrapper and pass that to methods that know the types they require:
public class DataElementBag
{
private IDictionary<Type, List<object>> _elements;
...
public void Add<T>(IDataElement<T> de)
{
Type t = typeof(T);
if(!this._elements.ContainsKey(t))
{
this._elements[t] = new List<object>();
}
this._elements[t].Add(de);
}
public void IEnumerable<IDataElement<T>> GetElementsByType<T>()
{
Type t = typeof(T);
return this._elements.ContainsKey(t)
? this._elements[t].Cast<IDataElement<T>>()
: Enumerable.Empty<T>();
}
}
来源:https://stackoverflow.com/questions/2045123/list-of-generic-interfaces