C# 我可以把T传递给类构造函数吗

C# 我可以把T传递给类构造函数吗,c#,.net,generics,c#-4.0,.net-4.0,C#,.net,Generics,C# 4.0,.net 4.0,我有一门课,比如: public MyClass { public myEnumType Status {get;set;} public DataTable Result{get;set;} } 因为DataTables很烂,所以我想实现一种面向对象的方法。但是,我有现有的代码,例如: public interface IData { MyClass AddData(int i); MyClass GetData(string Tablename); } 我想使用这个接

我有一门课,比如:

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;}
}

如果不在尖括号中声明泛型类型参数,则无法引用该参数,因此必须使用
IData
和/或
MyClass
类型,在这种情况下,不需要将其指定为构造函数的参数

如果您不能更改这些类型,您仍然可以使用动态分派避免显式强制转换。重载具有不同子类型的方法,并使用动态表达式将方法解析推迟到运行时,它将自动转换为子类型:

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

void DomSomtheingWithMyInheritedClass(MyClass x)
{
   DoSomethingWith((dynamic) x.Result);
}

为什么不创建一个像这样的通用接口呢

public interface IData<T>
{
    T AddData(int i);
    T GetData(string Tablename);
}
公共接口IData
{
T AddData(inti);
T GetData(字符串Tablename);
}
我们甚至可以有一个通用的实现:

public class MyGenericClass<T> : IData<T>
{
} 
公共类MyGenericClass:IData
{
} 
在C#中,表达式的类型由编译时其组成部分的类型决定。这意味着类似于上一个示例的东西(仅通过知道类的类型就可以知道属性的类型)无法工作

想象一下,如果编译了该类定义。那么你就有这个问题了:

// What would you use as the type of this variable?
??? val = GetMyClassFromSomewhere().MyOOClass;
当然,您可以使用
对象
,但是您对属性值一无所知,因此您必须先强制转换,然后才能对其执行任何操作


针对您的原始问题,通过从现有的
IData
接口派生一个新的通用接口,可以以兼容的方式扩展现有类型(有一些粗糙的边缘):

public interface IData<T> : IData
{
    new MyInheritedClass<T> AddData(int i);
    new MyInheritedClass<T> GetData(string Tablename);
}
公共接口IData:IData
{
新MyInheritedClass AddData(int i);
新的MyInheritedClass GetData(字符串Tablename);
}

虽然这是一个有点可怕的想法,但只要你想在T中输入的内容可以装入
MyClass
,你就可以编写一个如下的方法

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

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

我不确定我认为其中一个一定比另一个好,可能只会坚持使用强制类型转换。

如果你想让你的类具有泛型类型的属性,那么你的类必须是泛型的。问题是它的全部都在生产中,所以不能将IData更改为IData或将MyClass更改为MyClass,除非不需要这样做旧代码将编译,新代码可以使用TI在我的答案中添加了另一个建议。我没有想到动态,谢谢,但是我希望在很多地方都使用这个强类型的数据和MyClass,所以除非T不是必需的,并且旧代码将通过指定T来编译,否则它将工作。通过在IData中指定新关键字,编译器是否仍然假设您已经实现了IData方法,并且如果IData向其中添加了新方法,则IData将运行失败,因为并非所有方法都已实现?通过说
:IData
,将继承
IData
的所有成员。
new
关键字允许添加与来自
IData
的函数具有相同签名的新函数(并隐藏它们)。如果实现
IData
,则还必须显式地实现原始
IData
方法(可能只需调用
IData
方法)。这就是我所说的“粗糙边缘”。哦,好吧,我确实走了这条路,但我只是认为这是浪费代码。但是,如果显式方法只是返回IData,可能不会太糟糕
var result = (DerivedMyClass)obj.Result;
var result = obj.GetResult<DerivedMyClass>();