List of Common Interfaces

If I have a common interface with several implementing classes, for example:

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 transfer a collection of implementing classes of different types without resorting to transfer as an object.

It seems that it is not possible to define the return values ​​as

 public IDataElement<T>[] GetData() 

or

 public IDataElement<object>[] GetData() 

Any suggestions?

+6
generics c # interface
source share
2 answers

You can, of course, declare:

 public IDataElement<T>[] GetData<T>() 

and

 public IDataElement<object>[] GetData() 
  • although the latter is probably not what you need (your interface will not be an option even in C # 4, as it uses T both as input and output position, even if it is an option, you cannot use this variance for types of values). The first requires the caller to indicate <T> , for example.

    foo.GetData<string>();

Is that good for you?

It is impossible to express a "collection of an object, each of which implements an IDataElement<T> for another T", unless you give it an unrelated base class in which you could simply use IList<IDataElement> . In this case, the non-generic IDataElement may have the DataElement property, leaving the Value property in the general interface:

 public interface IDataElement { int DataElement { get; set; } } public interface IDataElement<T> : IDataElement { T Value { get; set; } } 

Is this useful in your particular situation?

It is unclear how you want to use a collection of data elements without knowing their types ... if the above does not help you, perhaps you could say more about what you expect from collections.

+4
source share

No, you cannot do this — the only options — or use a non-common interface:

 public interface IDataElement { int DataElement { get; set; } object Value { get; set; } } 

Alternatively, create a wrapper and pass it to methods that know the required types:

 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>(); } } 
+3
source share

All Articles