Из вашего вопроса:
public class Three<T> where T : BaseMapClass<dynamic, dynamic>
dynamic
не используется таким образом и не имеет ничего общего с генериками. В основном это object
, который поддерживает любой метод / свойство / поле и использует компиляцию во время выполнения для получения доступа к каждому методу / свойству / полю.
BaseMapClass<int, string> myVar = new BaseMapClass<int, string>();
object myVarAsObject = myVar;
Console.WriteLine(myVarAsObject.Thing1); // Won't compile
dynamic myVarAsDynamic = myVar;
Console.WriteLine(myVarAsDynamic.Thing1); // Will compile to a runnable program
Это не волшебная пуля, и она все равно выдаст исключение во время выполнения - RuntimeBinderException
- потому что Thing1 / Thing2 равны protected
.
Это благословение и проклятие использования dynamic
компиляции во время выполнения:)
Решение (чтобы ваш код компилировался)
Ваш третий пример имеет смысл. Здесь он сочетается с вашим существующим кодом:
public class Three<T1, T2, T3> where T1 : BaseMapClass<T2, T3>
{
IEnumerable<T2> Type1Things;
IEnumerable<T3> Type2Things:
}
Хотя вы все равно будете наследовать:
protected T2 Thing1; // Note: T1 of base type becomes T2 of the outer type
protected T3 Thing2; // Note: T2 of base type becomes T3 of the outer type
Если это нежелательно, не наследуйте от BaseMapClass
и не изменяйте его определение.
Предложения по окончательному оформлению
Если это не поможет вам решить исходную проблему, возможно, вы захотите опубликовать свой код на сайте Code Review и посмотреть, сможете ли вы получить отзыв о своем дизайне.
Вначале я думал, что вам следует выяснить, имеет ли смысл использовать interface
в вашем проекте, а не наследовать от конкретных типов.
Также посмотрите, существуют ли в платформе .Net существующие типы, которые соответствуют вашим целям, вместо того, чтобы придумывать новые (например, Tuple<T1, T2>
или, возможно, Dictionary<T1, T2>
).