Просмотрите код ниже, это, на мой взгляд, похоже на то, что вы пытаетесь:
namespace LibGeneric
{
public interface IArgs { }
public interface IOut { }
public class LibClassGeneric<TArgs,TOut>
where TArgs:IArgs
where TOut:IOut
{
public static Func<TArgs,TOut> GetFunc()
{
return (DataParams p) => new OutObject();
}
}
public class DataParams : IArgs { }
public class OutObject : IOut { }
}
Следующая строка является ошибкой компиляции по следующей причине:
return (DataParams p) => new OutObject();
- Нет совместимости типов между
TArgs, DataParams
и TOut,OutObject
- Что вы пытаетесь сделать, если базовый интерфейс или класс одинаковы, то два типа могут быть назначены другим , что неверно
- Для функции Generi c / Fun c Делегат для компиляции вам нужно присвоить ему что-то, что принимает
TArgs
в качестве ввода и TOut
в качестве вывода, теперь они имеют ограничения, которые необходимо проверить, что вы не можете добавить какой-либо код во время компиляции, который не соответствует ограничению. - Только при вызове
Func<TArgs,TOut> GetFunc()
вы сможете заполнить DataParams
и OutObject
, не при определении универсального c определения
Теперь рассмотрим это определение кода Generi c:
public class LibClassGeneric<TArgs,TOut>
where TArgs:IArgs
where TOut:IOut
{
public static Func<TArgs,TOut> GetFunc(TOut o)
{
return (args) => o;
}
}
- Это скомпилируется, так как вы референт вернитесь к правильным типам в определении метода
Вот как вы можете его использовать:
DataParams d = new DataParams();
OutObject o = new OutObject();
var resultFunc = LibClassGeneric<DataParams,OutObject>.GetFunc(o); // Call Func
resultFunc(d); // Invocation
Теперь вы добавляете любой уровень сложности при вызове и вызывая GetFunc()
, пока параметр типа точки не совпадет с
Редактировать 1:
Ниже приведен код предоставлено OP:
public static Func<IArgs, IOut> GetFunc(Processor p)
{
Func<IArgs, IOut> f = default;
switch (p)
{
case Processor.DoWork:
f = (p) => new OutObject(); //P is cat derived from IArgs
break;
case Processor.FooWork:
f = (p) => new OutObject(); //P is dog derived from IArgs
break;
}
return f;
}
Этот код возвращает забавный делегат c с IArgs
в качестве входных данных и IOut
в качестве выходных данных, что, будучи совместимым с Contravariant и Covariant, позволяет предоставлять параметр как производный класс IArgs
и результат может быть производным классом IOut
, его можно просто вызвать с помощью вызова следующим образом:
var func = GetFunc(Processor.DoWork);
var result = func(new Dog());
Теперь тип result
равен IOut
и нуждается в приведении типа к фактическому типа, нет никакого способа изменить его, кроме исследования точного типа с помощью отражения или выполнения приведения типа * stati c