We usually check for a null value that will not put nullables in an unbounded type.

Let's say I have the following method:

public static int CountNonNullMembers<T>(this IEnumerable<T> enumerable)
{
    if (enumerable == null) throw new ArgumentNullException("enumerable");
    int count = 0;
    foreach (var x in enumerable)
    {
        if (x != null) count++; 
    }
    return count;
}

And I have these 3 arrays ::

var ints = Enumerable.Range(0,10).ToArray();
var nullableInts = Array.ConvertAll(ints,x=>x as int?);
var strings = Array.ConvertAll(ints,x => x.ToString());

, . ints strings, 100 . nullableInts 2,5 . , int , struct, . Nullable<T> , x.HasValue. , , ? EqualityComparer<T>, null T, .

, , , , structs, Nullable<T> .

. ( ); . , . , , , (, , ), .

, .Count nullableInts strings ( ), . , . UnboxT Check<T>.IfNull . , :

    public static int CountNonNullMembers<T>(this IEnumerable<T> enumerable)
    {
        return enumerable.Count(Check<T>.IfNull.Invoke);
    }

?

+3
3

UnboxT. , ::

public static class Check<T>
{
            public static readonly Predicate<T> IfNull = CreateIfNullDelegate();
            private static bool AlwaysFalse(T obj)
            {
                return false;
            }

            private static bool ForRefType(T obj)
            {
                return object.ReferenceEquals(obj, null);
            }

            private static bool ForNullable<Tu>(Tu? obj) where Tu:struct
            {
                return !obj.HasValue;
            }
            private static Predicate<T> CreateIfNullDelegate()
            {
                if (!typeof(T).IsValueType)
                    return ForRefType;
                else
                {
                    Type underlying;
                    if ((underlying = Nullable.GetUnderlyingType(typeof(T))) != null)
                    {
                        return Delegate.CreateDelegate(
                            typeof(Predicate<T>),
                            typeof(Check<T>)
                                .GetMethod("ForNullable",BindingFlags.NonPublic | BindingFlags.Static)
                                    .MakeGenericMethod(underlying)
                        ) as Predicate<T>;
                    }
                    else
                    {
                        return AlwaysFalse;
                    }
                }
            }
        }

, . Strings , , .

+1

:

public static int CountNonNull<T>(this IEnumerable<T> source)
    where T : class
{
    return source.Count(x => x != null);
}

public static int CountNonNull<T>(this IEnumerable<Nullable<T>> source)
    where T : struct
{
    return source.Count(x => x.HasValue);
}

-nullable structs, .

+1

Although this is not necessarily better than your method, it does not require a whole class:

static Dictionary<Type, object> NullChecks = new Dictionary<Type, object>();
public static Func<T, bool> MakeNullCheck<T>()
{
    object obj;
    Func<T, bool> func;
    if (NullChecks.TryGetValue(typeof(T), out obj))
        return (Func<T, bool>)obj;
    if (typeof(T).IsClass)
        func = x => x != null;
    else if (Nullable.GetUnderlyingType(typeof(T)) != null)
    {
        var param = Expression.Parameter(typeof(T));
        func = Expression.Lambda<Func<T, bool>>(
            Expression.Property(param, typeof(T).GetProperty("HasValue")), param).Compile();
    }
    else
        func = x => false;
    NullChecks[typeof(T)] = func;
    return func;
}
0
source

Source: https://habr.com/ru/post/1770972/


All Articles