Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 指定泛型类,其中T应为其他类型的子类_C#_Generics - Fatal编程技术网

C# 指定泛型类,其中T应为其他类型的子类

C# 指定泛型类,其中T应为其他类型的子类,c#,generics,C#,Generics,这就是我想做的,甚至不确定是否可能 我正在创建BaseViewModel,我希望它接受从实体继承的类型 考虑以下代码: public abstract class BaseViewModel<T> : NotificationObject, INavigationAware { public T MyEntity; public SomeMethod() { MyEntity.SomeEntityProperty = SomeValue; } } 公共抽象类BaseViewM

这就是我想做的,甚至不确定是否可能

我正在创建
BaseViewModel
,我希望它接受从
实体继承的类型

考虑以下代码:

public abstract class BaseViewModel<T> : NotificationObject, INavigationAware
{

public T MyEntity;

public SomeMethod()
{
MyEntity.SomeEntityProperty = SomeValue;
}

}
公共抽象类BaseViewModel:NotificationObject,INavigationAware
{
公共卫生;
公共方法()
{
MyEntity.SomeEntityProperty=SomeValue;
}
}
所以,我想说我的
T
继承自
实体
,因此我知道它将具有某种实体属性

这可能吗?

公共抽象类BaseViewModel:
public abstract class BaseViewModel<T> :
    NotificationObject,
    INavigationAware

    where T : Entity
{

    public T MyEntity;

    public SomeMethod()
    {
        MyEntity.SomeEntityProperty = SomeValue;
    }

}
通知对象, 无活力意识 其中T:实体 { 公共卫生; 公共方法() { MyEntity.SomeEntityProperty=SomeValue; } }
只需使用
where
关键字:

public abstract class BaseViewModel<T> : NotificationObject, INavigationAware
    where T:Entity
{
...
公共抽象类BaseViewModel:NotificationObject,INavigationAware
其中T:实体
{
...
尝试使用约束:

public abstract class BaseViewModel<T> : NotificationObject, INavigationAware
    where T : Entity
{
    public T MyEntity;

    public SomeMethod()
    {
        MyEntity.SomeEntityProperty = SomeValue;
    }
}
公共抽象类BaseViewModel:NotificationObject,INavigationAware
其中T:实体
{
公共卫生;
公共方法()
{
MyEntity.SomeEntityProperty=SomeValue;
}
}

Salvatore的回答完全正确,我只是想更好地描述一下这个概念

您需要的是一个“泛型类型约束”;以指定用作T的类型必须符合某些行为(例如从比object派生得多的对象或接口派生),从而增加您可以在不进一步强制转换的情况下对该对象执行的操作(这在泛型中通常是要避免的)

正如Salvatore的回答所示,GTC是使用“where”关键字定义的:

公共抽象类BaseViewModel:
通知对象,
无活力意识
式中T:实体;
{
...
这个GTC基本上说明了任何T都必须从实体派生(无论多么远程)。这允许您将T视为一个实体(新T的实例化除外;这需要额外的GTC),而不管实际泛型参数类型是如何从实体派生的。您可以调用实体上显示的任何方法,并获取/设置任何字段或属性

您还可以指定:

  • 类型必须是类(
    其中T:class
    ),或者必须是ValueType(
    其中T:struct
    )。这允许或阻止将T实例比较和赋值为null,也允许或阻止使用null合并运算符
    ??
  • 类型必须具有无参数构造函数(
    where T:new()
    )。这允许使用
    new
    关键字实例化Ts,方法是在编译时确保用作Ts的所有类型都具有不带参数的构造函数

很抱歉,对6年前的响应进行了死记硬背,但如何指定特定的构造函数签名?例如,T:new(int,float)。这是我能找到的关于此功能的唯一参考,编译器似乎不喜欢它,但如果确实有办法定义它的话,它显然是一个有用的约束。@SebAndraos-不可能;这在最初的帖子中是一个错误。唯一与构造函数直接相关的通用约束是默认构造函数constraint需要任意T的无参数构造函数。您可以定义其他约束,以确保特定构造函数(或工厂方法)签名存在,但它不像“where T:new(int,string)”那样通用。
public abstract class BaseViewModel<T> :
    NotificationObject,
    INavigationAware

    where T : Entity;
{
   ...