Если у меня есть универсальный интерфейс с несколькими классами с реализацией, такими как:
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; }
}
Действительно ли возможно передать набор классов с реализацией отличающихся типов, не имея необходимость обращаться к передаче как объект.
Это, кажется, не возможно определить возвращаемые значения как
public IDataElement<T>[] GetData()
или
public IDataElement<object>[] GetData()
Какие-либо предложения?
Вы, конечно, можете объявить:
public IDataElement<T>[] GetData<T>()
и
public IDataElement<object>[] GetData()
хотя последнее, вероятно, не то, что вам нужно (ваш интерфейс не будет вариантом даже в C# 4, так как он использует T
как во входной, так и во выходной позиции; даже если бы он был вариантом, вы не смогли бы использовать эту дисперсию для типов значений). Первая потребует от вызывающего абонента указать
, например,
foo.GetData
Это вас устраивает?
Нет способа выразить "коллекцию объектов, каждый из которых реализует IDataElement
для другой T", если только вы также не дадите ему неэнергетический базовый класс, в котором вы можете просто использовать IList
. В этом случае неэнергетический IDataElement
может иметь свойство DataElement
, оставляя свойство Value
в общем интерфейсе:
public interface IDataElement
{
int DataElement { get; set; }
}
public interface IDataElement<T> : IDataElement
{
T Value { get; set; }
}
Это полезно в вашей конкретной ситуации?
Не ясно, как вы захотите использовать коллекцию элементов данных, не зная их типов... если вышесказанное не поможет вам, может быть, вы могли бы сказать больше о том, что вы ожидали сделать с этими коллекциями.
Нет, вы не можете это сделать - единственными вариантами являются либо использование нерегического интерфейса:
public interface IDataElement
{
int DataElement { get; set; }
object Value { get; set; }
}
. В качестве альтернативы создайте обертку и пропустите, что к способам, которые знают, что они требуют:
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>();
}
}