简体   繁体   English

是否可以在C#泛型方法中定义“not Nullable <T>”约束?

[英]Is it possible to define a “not Nullable<T>” constraint in a C# generic method?

In C#, the Nullable<T> type does not satisfy the where struct generic constraint (while AFAK this is techically a struct). 在C#中, Nullable<T>类型不满足where struct泛型约束(而AFAK这在技术上是一个结构)。 This can be used to specify that the generic argument has to be a non-nullable value type : 这可用于指定泛型参数必须是不可为空的值类型:

T DoSomething<T>() where T : struct
{
   //... 
} 
DoSomething<int?>(); //not ok
DoSomething<int>();  //ok

And of course, Nullable<T> also does not satisfy the reference type where class constraint : 当然, Nullable<T>也不满足引用类型where class约束:

T DoSomething<T>() where T : class
{
   //...
} 
DoSomething<int?>(); //not ok
DoSomething<Foo>();  //ok

Is this possible to define a constraint such as it has to be a reference type or a value type but not a Nullable value type ? 这是否可以定义约束,例如它必须是引用类型或值类型但不是Nullable值类型?

Something like this : 像这样的东西:

void DoSomething<T>() where T : class, struct //wont compile!
{    
   //...   
} 
DoSomething<int?>(); //not ok
DoSomething<int>();  //ok
DoSomething<Foo>();  //ok

As noted in a comment, you can do this with overloads and parameters (which can be optional). 如评论中所述,您可以使用重载参数(可以是可选的)来执行此操作。 I blogged about this a while ago, but in your case you'd want: 刚刚在博客上写过这篇文章 ,但在你的情况下,你想要:

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)
    {
        ...
    }
}

It's ugly, but it works: 这很难看,但它有效:

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)

No, it's not possible on the declaration side. 不,在宣言方面是不可能的。 It's either struct OR class . 它是struct OR class However, you can check the typeof(T) at run-time to ensure T is Nullable<T2> 但是,您可以在运行时检查typeof(T)以确保TNullable<T2>

Type type = typeof(T);
if(Nullable.GetUnderlyingType(type) == null)
    throw new Exception();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM