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)
See more on this question at Stackoverflow