简体   繁体   中英

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). 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 :

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 ?

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 . However, you can check the typeof(T) at run-time to ensure T is Nullable<T2>

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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