Кастинг System.Func <T> - PullRequest
       40

Кастинг System.Func <T>

3 голосов
/ 20 марта 2012

Я перефакторинг некоторого кода, который использует следующую конструкцию.То, что я хотел бы сделать, это сделать этот универсальный, чтобы я мог иметь другие типы параметров в Func.

IDictionary<string, Func<Employee, string>>

Я попытался использовать:

IDictionary<string, Func<Object, string>>

Затем приведение егоназад:

(IDictionary<string, Func<Object, string>>)myDictionary

Но я получаю исключение, говорящее, что я не могу привести

Невозможно привести объект типа System.Collections.Generic.Dictionary 2[System.String,System.Func 2...

Я играл с дженериками, но это, кажется, дошло до того, что я не смог настроить и родовое поле в своем классе

private IDictionary<string, Func<T, string>> lineSpecification;

Идетвокруг в кругах, так что любые указатели будут оценены.

РЕДАКТИРОВАТЬ:

Это полное сообщение об исключении, которое я получаю:

System.InvalidCastException : Unable to cast object of type 'System.Collections.Generic.Dictionary`2[System.String,System.Func`2[DataObjects.Employee,System.String]]' to type 'System.Collections.Generic.IDictionary`2[System.String,System.Object]'.

Ответы [ 3 ]

5 голосов
/ 20 марта 2012

Это было бы небезопасно.

Если бы это было законно, что бы произошло, если бы вы передали Car одному из приведенных значений (которое на самом деле Func<Employee, string>)?

2 голосов
/ 20 марта 2012

Вместо этого введите словарь как IDictionary<string, object> и приведите результирующее значение:

IDictionary<string, object> myDictionary = new Dictionary<string, object>();
var myDelegate = (Func<Employee, string>)myDictionary["my employee delegate"];

Конечно, это не удастся, если вы попытаетесь привести неверный тип Func, поэтому вы должны быть уверены, что знаете, какойкарта ключей, к которой относится тип Func.

0 голосов
/ 20 марта 2012

Похоже, вы хотите, чтобы ваш словарь имел значения различного типа;другими словами, что в одном словаре могут храниться Func<Employee, string> и Func<Customer, string>.

Если это так, то у вас в основном нет другого выбора, кроме как использовать общий базовый тип для типа TValueаргумент, и приведите делегатов при извлечении их из словаря.Общий базовый тип может быть System.Delegate или System.Object.

(На самом деле есть и другие варианты, кроме этого, но они просто переносят приведение к другой части проекта. Например, вы могли бынаписать класс-обертку, который будет обрабатывать кастинг для вас. Однако такие решения обычно не выдерживают анализа затрат и выгод.)

Мой словарь всегда будет иметь только один и тот же тип, но вразные сценарии, я хочу, чтобы он мог содержать разные типы.Проблема, с которой я сталкиваюсь, заключается в том, что приведение из Func в Func вызывает исключение.

В этом случае непонятно, почему вы хотите иметь Dictionary<string, Func<Object, string>> вместо Dictionary<string, Func<Employee, string>>.Если любой заданный словарь будет содержать только один тип делегата, то создайте словарь соответствующим образом:

Dictionary<string, Func<Employee, string>> dict = new Dictionary<string, Func<Employee, string>>();

Если словарь является членом универсального класса или локальной переменной или параметром универсального метода, выможно использовать параметры типа в объявлении словаря:

class Processor<T>
{
     void Process(T value, Dictionary<string, Func<T, string>> functions) { //... }
}
...