Обновление в .NET с использованием дженериков - PullRequest
1 голос
/ 29 марта 2009

Итак, у меня есть такой класс:

public class A { 
  internal A(int i) { ... }
  public int Foo { get; set; }
}

Этот класс затем наследуется группой сгенерированных классов, например:

public class B : A {
  ...
}

Конструктор на основе int не предоставляется унаследованному классу (по причинам дизайна я не хочу, чтобы он отображался). В моей библиотеке, которая содержит определение для класса A, у меня есть такой метод:

public T Load<T>() where T : A {
  //do some stuff, create an instance of T from an int, then return it
}

А потом я бы использовал это так:

B b = Helper.Load<B>();

Поскольку конструктор, который я хочу использовать, не предоставляется классу B, когда я делаю typeof(T).GetConstructor(typeof(int)) Я не получаю конструктор обратно, поэтому я хочу подумать, что я сделаю это:

return (T)new A(/*some int */);

Но это дает мне ошибку времени выполнения System.InvalidCastException, что я не могу привести тип A к типу B.

Как мне добиться этого апскейтинга?

Ответы [ 4 ]

3 голосов
/ 29 марта 2009

Вы можете просто использовать конструкторы по умолчанию, чтобы создавать экземпляры объектов типа T с ограничением new (). Тогда класс A может иметь виртуальный (или абстрактный по вашему вкусу) метод, который принимает int в качестве аргумента и инициализирует объект после запуска конструктора.

public class A {
    internal A() { }
    internal Initialize(int i) { Foo = i; }
    public int Foo { get; set; }
}

public class B : A { 
    internal B() { }
}

...

public T Load<T>() where T : A, new() {
    var ret = new T();
    ret.Initialize(i);
    return ret;
}

Если вы намереваетесь использовать какой-то фабричный шаблон, вам не нужно стесняться инициализировать части объекта вне вызова конструктора, если это делается до того, как вы вернете объект в управление вызывающей стороны.

1 голос
/ 29 марта 2009

Вы не можете использовать upcast от A до B в вашем примере, потому что:

return (T)new A(/*some int */);

Создает экземпляр A, который не a B. То, что "B является A", не означает "A является B" Сначала вам нужно создать экземпляр B, привести его к A, сделать то, что вы хотите, а затем превратить его обратно в B.

Я не уверен, что это скомпилируется, но вы можете попробовать это:

T blah = new T(5); //this means your B will need to implement a int constructor
A blah2 = (A)blah;
//operate on A specific operations in blah2
T upcasted = (T)blah2;
//alternatively
T upcasted = blah2 as T;

Рассмотрите возможность рефакторинга вашего конструктора, чтобы вы инициализировали целое число как свойство, а не параметр конструктора. Я стараюсь иметь конструкторы по умолчанию (без параметров), чтобы общий код мог легко создать экземпляр класса.

1 голос
/ 29 марта 2009

Из того, что я понял, T происходит от A, поэтому вы не можете привести A к T.

0 голосов
/ 29 марта 2009

Вы не можете сделать это, измените свой дизайн.

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