是否可以定义一个;不可为空<;T>&引用;C#泛型方法中的约束?

是否可以定义一个;不可为空<;T>&引用;C#泛型方法中的约束?,c#,generics,nullable,non-nullable,generic-constraints,C#,Generics,Nullable,Non Nullable,Generic Constraints,在C#中,Nullable类型不满足wherestruct泛型约束(而AFAK这在技术上是一个结构)。这可用于指定泛型参数必须是不可为null的值类型: T DoSomething<T>() where T : struct { //... } DoSomething<int?>(); //not ok DoSomething<int>(); //ok 这是否可以定义约束,例如它必须是引用类型或值类型,但不能是可为空的值类型? 大概是这样的: v

在C#中,
Nullable
类型不满足
where
struct
泛型约束(而AFAK这在技术上是一个结构)。这可用于指定泛型参数必须是不可为null的值类型:

T DoSomething<T>() where T : struct
{
   //... 
} 
DoSomething<int?>(); //not ok
DoSomething<int>();  //ok
这是否可以定义约束,例如它必须是引用类型或值类型,但不能是可为空的值类型?

大概是这样的:

void DoSomething<T>() where T : class, struct //wont compile!
{    
   //...   
} 
DoSomething<int?>(); //not ok
DoSomething<int>();  //ok
DoSomething<Foo>();  //ok
void DoSomething(),其中T:class,struct//无法编译!
{    
//...   
} 
DoSomething()//不好
DoSomething()//好啊
DoSomething()//好啊

不,在申报方面不可能。它是
struct
class
。 但是,您可以在运行时检查
typeof(T)
,以确保
T
Nullable


如注释中所述,可以使用重载和参数(可以是可选的)来完成此操作。我刚才说过,但在你的情况下,你会想要:

public class ClassConstraint<T> where T : class
{
}

public class SomeClass<TViewModel>
{
    public void Add<TValue>(Func<TViewModel, TValue> expression,
                            ClassConstraint<TValue> ignored = null)
        where TValue : class
    {
        AddImpl(expression);
    }

    public void Add<TValue>(Func<TViewModel, TValue> expression,
                            Nullable<TValue> ignored = null)
        where TValue : struct
    {
        AddImpl(expression);
    }

    // No constraints
    private void AddImpl<TValue>(Func<TViewModel, TValue> expression)
    {
        ...
    }
}
公共类类约束,其中T:class
{
}
公共类
{
公共void Add(Func表达式,
ClassConstraint已忽略(默认值=null)
其中TValue:类
{
AddImpl(表达式);
}
公共void Add(Func表达式,
null可忽略=null)
其中TValue:struct
{
AddImpl(表达式);
}
//无约束
私有void AddImpl(Func表达式)
{
...
}
}
虽然很难看,但它很管用:

var z = new SomeClass<string>();
z.Add(x => x.Length);        // Valid (non-nullable value type)
z.Add(x => x);               // Valid (reference type)
z.Add(x => new DateTime?()); // Invalid (nullable value type)
var z=newsomeclass();
z、 添加(x=>x.Length);//有效(不可为空的值类型)
z、 加(x=>x);//有效(引用类型)
z、 添加(x=>newdatetime?());//无效(可为空的值类型)

除了可为空之外的所有内容?这很难。为什么要这样做?据我所知,使用泛型约束是不可能的,所以没有编译时检查可用于此。不过,您可以在运行时检查实际的类型。您可以使用重载和可选参数进行检查,但这非常糟糕。看看你能否给我们提供更多关于你想要实现的目标的信息,我们可以帮你更多。@sloth:我有一个
Add(Func expression)
方法,我想确保它只用于不可为空的类型(例如:
Add(x=>x.Id)
OK
Add(x=>x.CreationDate.Value)
OK
Add(x=>x.CreationDate)
NOK)。
public class ClassConstraint<T> where T : class
{
}

public class SomeClass<TViewModel>
{
    public void Add<TValue>(Func<TViewModel, TValue> expression,
                            ClassConstraint<TValue> ignored = null)
        where TValue : class
    {
        AddImpl(expression);
    }

    public void Add<TValue>(Func<TViewModel, TValue> expression,
                            Nullable<TValue> ignored = null)
        where TValue : struct
    {
        AddImpl(expression);
    }

    // No constraints
    private void AddImpl<TValue>(Func<TViewModel, TValue> expression)
    {
        ...
    }
}
var z = new SomeClass<string>();
z.Add(x => x.Length);        // Valid (non-nullable value type)
z.Add(x => x);               // Valid (reference type)
z.Add(x => new DateTime?()); // Invalid (nullable value type)