Могу ли я передать T в конструктор класса - PullRequest
0 голосов
/ 21 сентября 2011

У меня есть такой класс:

public MyClass
{
   public myEnumType Status {get;set;}
   public DataTable Result{get;set;}
}

Поскольку DataTables отстой, я хочу реализовать объектно-ориентированный подход. Однако у меня есть существующий код, такой как:

public interface IData
{
  MyClass AddData(int i);
  MyClass GetData(string Tablename);
}

Я хотел бы использовать этот интерфейс, но вместо того, чтобы возвращать DataTable, я хочу вернуть какой-то объект, например класс / Person.

Я действительно думал о создании нового класса, который унаследовал MyClass следующим образом:

public MyInheritedClass<T> : MyClass
{
  public new T Result{get;set;}
}

Однако всякий раз, когда вы получаете данные из класса, который реализует интерфейс, вам придется приводить результат методов из MyClass в MyInheritedClass. Поэтому мне было интересно, есть ли способ использовать существующий MyClass, чтобы поместить конструктор, который передает универсальный тип, так что в итоге я получил что-то вроде

public MyClass
{
   public MyClass(T MyObjectOrientatedClass)
   {
      MyOOClass = MyObjectOrientatedClass;
   }
   public myEnumType Status {get;set;}
   public DataTable Result{get;set;}
   public T MyOOClass {get;set;}
}

Ответы [ 4 ]

1 голос
/ 21 сентября 2011

В C # типы выражений определяются типами составляющих их частей во время компиляции.Это означает, что что-то похожее на ваш последний пример (где тип свойства невозможно узнать, просто зная тип класса) не может работать.

Представьте, что определение этого класса скомпилировано.Тогда у вас возникнет следующая проблема:

// What would you use as the type of this variable?
??? val = GetMyClassFromSomewhere().MyOOClass;

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


Обращаясь к исходной проблеме, можно (с несколькими грубыми углами) совместить существующие типы с помощью совместимого создания нового универсального интерфейса из существующего интерфейса IData:

public interface IData<T> : IData
{
    new MyInheritedClass<T> AddData(int i);
    new MyInheritedClass<T> GetData(string Tablename);
}
1 голос
/ 21 сентября 2011

Нельзя ссылаться на параметр универсального типа, не указав его в заостренных скобках, поэтому вам придется либо иметь тип IData<T> и / или MyClass<T>, в этом случае вам не нужноукажите его как параметр для конструктора.

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

void DoSomethingWith(Person p) { ... }
void DoSomethingWith(AnotherClass x) { ... }

void DomSomtheingWithMyInheritedClass(MyClass x)
{
   DoSomethingWith((dynamic) x.Result);
}
0 голосов
/ 22 сентября 2011

Хотя это несколько ужасная идея, поскольку то, что вы хотите поместить в T, можно поместить в MyClass, вы можете написать метод, подобный ...

public T GetResult<T>() where T : MyClass
{
    return (T)Result;
}

Довольно грубый,но это позволит вам "заключить" актерский состав.В действительности, однако, мы говорим о разнице между ...

var result = (DerivedMyClass)obj.Result;

... и ...

var result = obj.GetResult<DerivedMyClass>();

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

0 голосов
/ 21 сентября 2011

Почему бы не создать универсальный интерфейс, такой как

public interface IData<T>
{
    T AddData(int i);
    T GetData(string Tablename);
}

, тогда у нас даже будет общая реализация:

public class MyGenericClass<T> : IData<T>
{
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...