C # Generics / Наследование динамики - PullRequest
0 голосов
/ 03 ноября 2011

Допустим, у меня есть эти классы:

public class BaseMapClass<T1, T2>
{
   protected T1 Thing1;
   protected T2 Thing2;
}

public class InstanceMapClass1 : BaseMapClass<Type1, Type2>
{
      public InstanceMapClass(Type1 x, Type2 y)
      {
         Thing1 = x;
         Thing2 = y
      }
}

public class InstanceMapClass2 : BaseMapClass<Type3, Type4>
{
      public InstanceMapClass(Type3 x, Type4 y)
      {
         Thing1 = x;
         Thing2 = y
      }
}

Теперь у меня есть третий класс, в идеале я хотел бы иметь два универсальных IEnumerables, которые принимают их тип на основе обобщенных типов, переданных в BaseMapClass

public class Three<T> where T : BaseMapClass<dynamic, dynamic>
{
   IEnumerable<??> TypeXThings; // should be of the first dynamic type
   IEnumerable<??> TypeYThings; // should be of the second dynamic type
}

, поэтому, если я создал новый класс

Three<InstanceMapClass1> three = new Three<InstanceMapClass1>();
Type1 t1 = three.TypeXThings.FirstOrDefault();

или

Three<InstanceMapClass2> another = new Three<InstanceMapClass2>();
Type3 t3 = another.TypeXThings.FirstOrDefault();

Используя динамику и обобщенные элементы, можно установить тип этих IEnumerables науниверсальные типы BaseMapClass во время выполнения?Что я действительно хочу, так это уметь передавать этот класс отображения, а затем создавать коллекции на основе их общих параметров.Я чувствую, что поступаю неправильно, но я могу думать только о том, как это сделать:

public class Three<T1, T2, T3>
{
   IEnumerable<T2> Type1Things;
   IEnumerable<T3> Type2Things:
}

Спасибо!Кроме того, я понимаю, что это может не иметь смысла, поэтому, пожалуйста, дайте мне знать, где требуется разъяснение.

1 Ответ

3 голосов
/ 04 ноября 2011

Из вашего вопроса:

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>).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...