#c# #c#-4.0 #covariance #contravariance
#c# #c #-4.0 #ковариация #контравариантность
Вопрос:
Я пытаюсь создать массив класса DataTableColumn, но, к сожалению, я схожу с ума от этого. К настоящему времени это то, что я пытался сделать без какого-либо успеха
public interface IDataTableColumn<out TValue> {
string Expression { get; }
DataTableFilterType FilterType { get; }
TValue Cast(string value);
}
public class DataTableColumn<TValue> : IDataTableColumn<TValue> {
public DataTableColumn(string expression, DataTableFilterType filterType = DataTableFilterType.Equal) {
Expression = expression;
FilterType = filterType;
}
public string Expression { get; private set; }
public DataTableFilterType FilterType { get; private set; }
public TValue Cast(string value) {
return value.As<TValue>();
}
}
Мой массив ДОЛЖЕН быть похож
private readonly IDataTableColumn<object>[] _columns = {
new DataTableColumn<int>("Id"), // ERROR
new DataTableColumn<string>("Description", DataTableFilterType.StartsWith), // SUCCESS
new DataTableColumn<DateTime?>("Date"), // ERROR
};
На самом деле работает так
private readonly dynamic[] _columns = {
new DataTableColumn<int>("Id"),
new DataTableColumn<string>("Description", DataTableFilterType.StartsWith),
new DataTableColumn<DateTime?>("Date"),
};
Я думаю, что использование dynamic — не лучший способ сделать это .. кто-нибудь, пролейте свет, пожалуйста!
Редактировать
черт, я забыл об ошибке
Не удается неявно преобразовать тип DataTableColumn< int >’ в ‘IDataTableColumn< object >’. Существует явное преобразование (вы пропускаете приведение?)
Не удается неявно преобразовать тип DataTableColumn< System.Дата-время? >’ в ‘IDataTableColumn< объект >’. Существует явное преобразование (вы пропускаете приведение?)
Ответ №1:
Я полагаю, это потому, что int
и DateTime
являются типами значений, которые не являются ковариантными с object
(они требуют упаковки). При компиляции вашего кода я получаю следующую ошибку:
covar.cs(23,13): error CS0266: Cannot implicitly convert type
'DataTableColumn<System.DateTime>' to 'IDataTableColumn<object>'.
An explicit conversion exists (are you missing a cast?)
Согласно MSDN, «Различия в универсальных интерфейсах (C # и Visual Basic)»:
Различия в универсальных интерфейсах поддерживаются только для ссылочных типов. Типы значений не поддерживают дисперсию. Например,
IEnumerable<int>
(IEnumerable(Of Integer)
в Visual Basic) не может быть неявно преобразовано вIEnumerable<object>
(IEnumerable(Of Object)
в Visual Basic), потому что целые числа представлены типом значения.
DataTableColumn<string>
работает, потому что он является прямым производным от object
.
Комментарии:
1. Но нет способа сделать что-то подобное? нет подхода?
2. @Kim, обычно ответ заключается в том, чтобы иметь
IFoo<T>
производную отIFoo
, а затем пусть ваш массив будет типаIFoo
. Ковариация работает для ссылочных типов , вот почему вы видите свою ошибку.3. Хорошо, все, я просто пытаюсь здесь найти «ответ» на мою проблему, а не причину проблемы. В любом случае спасибо.
4. @Kim: Ну, ответ в том, что ваша стратегия вряд ли будет осуществимой. Предложение @Anthony является распространенным подходом.
5. Я воспользуюсь предложением @Anthony’s. Спасибо за вас обоих.