C# generic type constraint for everything nullable

后端 未结 8 1999
无人共我
无人共我 2020-12-09 14:11

So I have this class:

public class Foo where T : ???
{
    private T item;

    public bool IsNull()
    {
        return item == null;
    }

}


        
相关标签:
8条回答
  • I don't know how to implement equivalent to OR in generics. However I can propose to use default key word in order to create null for nullable types and 0 value for structures:

    public class Foo<T>
    {
        private T item;
    
        public bool IsNullOrDefault()
        {
            return Equals(item, default(T));
        }
    }
    

    You could also implement you version of Nullable:

    class MyNullable<T> where T : struct
    {
        public T Value { get; set; }
    
        public static implicit operator T(MyNullable<T> value)
        {
            return value != null ? value.Value : default(T);
        }
    
        public static implicit operator MyNullable<T>(T value)
        {
            return new MyNullable<T> { Value = value };
        }
    }
    
    class Foo<T> where T : class
    {
        public T Item { get; set; }
    
        public bool IsNull()
        {
            return Item == null;
        }
    }
    

    Example:

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(new Foo<MyNullable<int>>().IsNull()); // true
            Console.WriteLine(new Foo<MyNullable<int>> {Item = 3}.IsNull()); // false
            Console.WriteLine(new Foo<object>().IsNull()); // true
            Console.WriteLine(new Foo<object> {Item = new object()}.IsNull()); // false
    
            var foo5 = new Foo<MyNullable<int>>();
            int integer = foo5.Item;
            Console.WriteLine(integer); // 0
    
            var foo6 = new Foo<MyNullable<double>>();
            double real = foo6.Item;
            Console.WriteLine(real); // 0
    
            var foo7 = new Foo<MyNullable<double>>();
            foo7.Item = null;
            Console.WriteLine(foo7.Item); // 0
            Console.WriteLine(foo7.IsNull()); // true
            foo7.Item = 3.5;
            Console.WriteLine(foo7.Item); // 3.5
            Console.WriteLine(foo7.IsNull()); // false
    
            // var foo5 = new Foo<int>(); // Not compile
        }
    }
    
    0 讨论(0)
  • 2020-12-09 15:10

    Such a type constraint is not possible. According to the documentation of type constraints there is not constraint that captures both the nullable and the reference types. Since constraints can only be combined in a conjunction, there is no way to create such a constraint by combination.

    You can, however, for your needs fall back to an unconstraint type parameter, since you can always check for == null. If the type is a value type the check will just always evaluate to false. Then you'll possibly get the R# warning "Possible compare of value type with null", which is not critical, as long as the semantics is right for you.

    An alternative could be to use

    object.Equals(value, default(T))
    

    instead of the null check, since default(T) where T : class is always null. This, however, means that you cannot distinguish weather a non-nullable value has never been set explicitly or was just set to its default value.

    0 讨论(0)
提交回复
热议问题