Is there a shorter way to write the following? (Something that would check for null without explicitly writing != null)
from item in list
where item.MyProperty != null
select item.MyProperty
You can use the OfType operator. It ignores null values in the source sequence. Just use the same type as MyProperty and it won't filter out anything else.
// given:
// public T MyProperty { get; }
var nonNullItems = list.Select(x => x.MyProperty).OfType<T>();
I would advise against this though. If you want to pick non-null values, what can be more explicit than saying you want "the MyProperties from the list that are not null"?
You could define your own extension method, but I wouldn't recommend that.
public static IEnumerable<TResult> SelectNonNull<T, TResult>(this IEnumerable<T> sequence,Func<T, TResult> projection)
{
return sequence.Select(projection).Where(e => e != null);
}
I don't like this one because it mixes two concerns. Projecting with Select and filtering your null values are separate operations and should not be combined into one method.
I'd rather define an extension method that only checks if the item isn't null:
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T> sequence)
{
return sequence.Where(e => e != null);
}
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> sequence)
where T : struct
{
return sequence.Where(e => e != null).Select(e => e.Value);
}
This has only a single purpose, checking for null. For nullable value types it converts to the non nullable equivalent, since it's useless to preserve the nullable wrapper for values which cannot be null.
With this method, your code becomes:
list.Select(item => item.MyProperty).WhereNotNull()
I tend to create a static class containing basic functions for cases like these. They allow me write expressions like
var myValues myItems.Select(x => x.Value).Where(Predicates.IsNotNull);
And the collection of predicate functions:
public static class Predicates
{
public static bool IsNull<T>(T value) where T : class
{
return value == null;
}
public static bool IsNotNull<T>(T value) where T : class
{
return value != null;
}
public static bool IsNull<T>(T? nullableValue) where T : struct
{
return !nullableValue.HasValue;
}
public static bool IsNotNull<T>(T? nullableValue) where T : struct
{
return nullableValue.HasValue;
}
public static bool HasValue<T>(T? nullableValue) where T : struct
{
return nullableValue.HasValue;
}
public static bool HasNoValue<T>(T? nullableValue) where T : struct
{
return !nullableValue.HasValue;
}
}
There is no way to skip a check if it exists.
// if you need to check if all items' MyProperty doesn't have null
if (list.All(x => x.MyProperty != null))
// do something
// or if you need to check if at least one items' property has doesn't have null
if (list.Any(x => x.MyProperty != null))
// do something
But you always have to check for null
get one column in the distinct select and ignore null values:
var items = db.table.Where(p => p.id!=null).GroupBy(p => p.id)
.Select(grp => grp.First().id)
.ToList();
This is adapted from CodesInChaos's extension method. The name is shorter (NotNull) and more importantly, restricts the type (T) to reference types with where T : class.
public static IEnumerable<T> NotNull<T>(this IEnumerable<T> source) where T : class
{
return source.Where(item => item != null);
}
I know i am a bit late to the party but I found a IMO very elegant sollution to this problem. I wrote an extension method to chain onto my LINQ queries:
public static IEnumerable<T> DiscardNullValues<T>(this IEnumerable<T?> nullable)
{
foreach (var item in nullable)
{
if (item is not null) yield return item;
}
}
Works like a charm.
This is a feature that have been proposed to the dotnet/runtime issue tracker.
See this comment that proposes a SelectNotNull function :
https://github.com/dotnet/runtime/issues/30381#issuecomment-806396119
Related
I'm confused why this doesn't work and what an alternative might be. I suppose I could create a non-null version of MaybeNull but this issue keeps recurring I'd have to make a lot of duplicate functions. The 'MaybeNull' extension is used in other places where the null is relevant, and like I say, there's a bunch of them with a similar setup.
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
public class MyClass
{
private List<string> ParseList(List<string> source)
{
var result = new List<string>();
//problem is this line
result.AddRange(source.Select(x => x.MaybeNull()).Where(x => x != null));
return result;
}
}
public static class StringExtensions
{
public static string? MaybeNull(this string? input)
{
if (input == null) return null;
return input + "modified";
}
}
#nullable disable
So despite the where clause it's trying to add string? items to the List<string> result which obviously won't work. I can make it work if I do a foreach
private List<string> ParseList2(List<string> source)
{
var result = new List<string>();
foreach (var item in source)
{
var modifiedItem = item.MaybeNull();
if (modifiedItem != null) result.Add(modifiedItem);
}
return result;
}
Something like this looks like it would work for a list of Int but not for string or other more complex types.
result.AddRange(source.Select(x => x.MaybeNull())
.Where(x => x != null)
.Select(x => x.Value));
Is there a way to achieve a similar result using a nice linq one liner?
EDIT: In response to comments, the actual code it isn't even a string (so string.IsNullOrEmpty isn't an option), it's a complex Class that gets modified in an extension which is designed to handle nulls. There are lots of extensions like this I'm now implementing nullable reference types on an established code base.
EDIT2: Part of the reason that this is bugging me is that ReSharper says "hey this foreach can be a linq statement! =D " and then it converts it into the invalid linq seen above -_-
This is because the compiler still sees the result from .Where() as a nullable T?
If you want to resolve this via LINQ, I'd recommend a custom extension method that tells the compiler your items aren't null.
You'll need to use alternative LINQ syntax
var nullable = new List<string?>
{
"Hello",
null,
"World"
};
var notNull = nullable.WhereNotNull();
Console.WriteLine(string.Join(',', notNull));
internal static class IEnumerableExtensions
{
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> enumerable)
where T : class
{
return from e in enumerable
where e is not null
select e;
}
}
// Outputs: Hello,World
so I have a generic function that calls a web service and converts it to whatever type you call the function with. However if you call CallUrl<SomeValue[]> - I don't want to return null, I want to return an empty list. I'm currently returning DefaultOrEmpty() - where that looks like:
private static T DefaultOrEmpty<T>()
{
return typeof(T).IsArray
? (T)(object)Array.CreateInstance(typeof(T).GetElementType()!, 0)
: default;
}
which works, but seems ridiculously complicated - is there a cleaner way to write this function?
Assuming by "collection", you mean an array, specifically, I don't see anything particularly wrong with your array initialization as it's perfectly understandable, but here's a slightly shorter method if that's what you're aiming for:
private static T DefaultOrEmpty<T>()
{
return typeof(T).IsArray
? (T)Activator.CreateInstance(typeof(T), 0)
: default;
}
Or to support multidimensional arrays (which were not supported in the original method):
private static T DefaultOrEmpty<T>()
{
if (typeof(T).IsArray)
{
var args = Enumerable.Repeat(0, typeof(T).GetArrayRank())
.Cast<object>()
.ToArray();
return (T)Activator.CreateInstance(typeof(T), args);
}
return default;
}
This is simple enough to just inline.
T[] DefaultOrEmpty<T>()
=> Array.Empty<T>();
If you sometimes return an array & sometimes a unary value, you could avoid the reflection by using function overloads and extension methods.
Here's an example:
public static class Extensions
{
//drop in replacement
public static T? DefaultOrEmpty<T>(this T? value)
=> value?? default;
public static T DefaultOrEmpty<T>(this T? value, T defaultValue)
=> value ?? defaultValue;
public static T DefaultOrEmpty<T>(this T? value, Func<T> defaultValueFactory)
=> value ?? defaultValueFactory();
//drop in replacement
public static T[] DefaultOrEmpty<T>(this T[]? value)
=> value ?? Array.Empty<T>();
public static T[] DefaultOrEmpty<T>(this T[]? value, Func<T[]> defaultValueFactory)
=> value ?? defaultValueFactory();
}
Which can be called like so:
int? num1 = null;
Console.WriteLine(num1.DefaultOrEmpty());
Console.WriteLine(num1.DefaultOrEmpty(99));
string[] names = null;
Console.WriteLine(names.DefaultOrEmpty().Length);
I created Enum ToFrendlyString function for my enums, but i cant use in Linq.
public enum MyEnum
{
Queued = 0,
[Description("In progress")]
In_progress = 2,
[Description("No answer")]
No_answer = 6,
}
public static class EnumToFrendlyString
{
public static string ToFrendlyString(this Enum value)
{
return value.GetEnumDescription();
}
public static string GetEnumDescription(this Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
var attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute),
false);
if (attributes.Length > 0)
return attributes[0].Description;
return value.ToString();
}
}
When i try to use this function in Linq, im getting error
var res = collection.AsQueryable().Where(p => p.UserID == UserID).OrderByDescending(p=> p.DateCreated).Select(p => new MyClass
{
Date = p.DateCreated.ToString(),
Status = p.Status.ToFrendlyString(),
}).Take(10).ToList();
If i make another function in same class, like
private string MyStatusToString(MyEnum status)
{
return status.ToFrendlyString();
}
and change my Linq to use this function, then everything works.
Error
Expression of type 'DAL.MyEnum' cannot be used for parameter of type 'System.Enum' of method 'System.String ToFrendlyString(System.Enum)'
I'm not sure you can use Enum as the Type for an extension method like that - try this instead. I've taken the liberty of tidying the code up a bit, feel free to ignore those changes :)
public static class EnumToFrendlyString
{
public static string ToFrendlyString<T>(this T value)
where T : struct
{
return value.GetEnumDescription();
}
public static string GetEnumDescription<T>(this T value)
where T : struct
{
return EnumDescriptionCache<T>.Descriptions[value];
}
private static class EnumDescriptionCache<T>
where T : struct
{
public static Dictionary<T, string> Descriptions =
Enum.GetValues(typeof(T))
.Cast<T>()
.ToDictionary(
value => value,
value => value.GetEnumDescriptionForCache());
}
private static string GetEnumDescriptionForCache<T>(this T value)
where T : struct
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("Only use with enums", "value");
}
var descriptionAttribute = typeof(T)
.GetField(value.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute), false)
.Cast<DescriptionAttribute>()
.FirstOrDefault();
return (descriptionAttribute != null)
? descriptionAttribute.Description
: value.ToString();
}
}
I've added a private, generic class to cache the descriptions for your enum members to avoid lots of runtime use of reflection. It looks a bit odd popping in and out of the class to first cache then retrieve the values, but it should work fine :)
The warning I gave in this answer still applies - the enum value passed to the dictionary isn't validated, so you could crash it by calling ((MyEnum)5367372).ToFrendlyString().
I am not sure but it can be that you didn t add the DAL project yet to your current project(Add reference -> projects in solutins -> Dal). Then it might work. (I had a similar issue once and this was my solution)
It seems the problem is that your collection is IQueryable<T> and the query provider is trying to translate your Select() into a query string.
One way to avoid that is to perform Select() in memory using IEnumerable<T>:
var res = collection.AsQueryable()
.Where(p => p.UserID == UserID)
.OrderByDescending(p=> p.DateCreated)
.Take(10)
.AsEnumerable()
.Select(p => new MyClass
{
Date = p.DateCreated.ToString(),
Status = p.Status.ToFrendlyString(),
})
.ToList();
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());
I wrote a little function to do a loop and time it for a million iterations. Applying it to ints and strings, it finishes in about 100 ms on my machine. For nullableInts, it takes 2.5 seconds.
As I understand the check for null on int doesn't make sense, so the compiler has a different template for non-nullable struct types, that removes null checks. But Nullable<T> does not have a template that converts the null check to x.HasValue. If I have an unconstrained function, how can I do a null check that will perform well? I can't use EqualityComparer<T>, as null might not be a member of T as there is no constraint.
Also it's impossible to have overloads that differ by constraint, so I can't, say, have one for structs, one for Nullable<T>, and one for classes.
The caller of the method is non-constrained. This is just an example (not the actual method); the method calling is non-constrained. I need to do some work against non-null members, and it's a generic method. I suppose I could write a version that doesn't do the check vs one that does (and consequently has a different signature), but it's seems very ugly and unneeded.
Also, the extension method .Count inexplicably performs horribly for NullableInts and strings, (equally bad), so it really isn't the right approach. This might be the delegate invocation, but I doubt it. Using the UnboxT style method of Check<T>.IfNull performs a lot better.
Okay, really weird switching the body of the count to this performs great:
public static int CountNonNullMembers<T>(this IEnumerable<T> enumerable)
{
return enumerable.Count(Check<T>.IfNull.Invoke);
}
Why?
You can constrain generic type parameters to reference types or values types:
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);
}
You don't need an overload for non-nullable structs, because they can't be null anyway.
Using the UnboxT approach works. But I'd also like something that doesn't require creating a static type::
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;
}
}
}
}
Using this approach everything performs about the same. Strings performs worse, but not so much worse than everything else.
While not necessarily better than your method, it doesn't 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;
}
Just for curiosity/convenience: C# provides two cool conditional expression features I know of:
string trimmed = (input == null) ? null : input.Trim();
and
string trimmed = (input ?? "").Trim();
I miss another such expression for a situation I face very often:
If the input reference is null, then the output should be null. Otherwise, the output should be the outcome of accessing a method or property of the input object.
I have done exactly that in my first example, but (input == null) ? null : input.Trim() is quite verbose and unreadable.
Is there another conditional expression for this case, or can I use the ?? operator elegantly?
Something like Groovy's null-safe dereferencing operator?
string zipCode = customer?.Address?.ZipCode;
I gather that the C# team has looked at this and found that it's not as simple to design elegantly as one might expect... although I haven't heard about the details of the problems.
I don't believe there's any such thing in the language at the moment, I'm afraid... and I haven't heard of any plans for it, although that's not to say it won't happen at some point.
EDIT: It's now going to be part of C# 6, as the "null-conditional operator".
Currently we can only write an extension method if you don't want to repeat yourself, I'm afraid.
public static string NullableTrim(this string s)
{
return s == null ? null : s.Trim();
}
You can choose between a custom Nullify class or a NullSafe extension method as described here: http://qualityofdata.com/2011/01/27/nullsafe-dereference-operator-in-c/
The usage will be as follows:
//Groovy:
bossName = Employee?.Supervisor?.Manager?.Boss?.Name
//C# Option 1:
bossName = Nullify.Get(Employee, e => e.Supervisor, s => s.Manager,
m => m.Boss, b => b.Name);
//C# Option 2:
bossName = Employee.NullSafe( e => e.Supervisor ).NullSafe( s => s.Boss )
.NullSafe( b => b.Name );
As a workaround you can use this which is based on Maybe monad.
public static Tout IfNotNull<Tin, Tout>(this Tin instance, Func<Tin, Tout> Output)
{
if (instance == null)
return default(Tout);
else
return Output(instance);
}
Use it this way:
int result = objectInstance.IfNotNull(r => 5);
var result = objectInstance.IfNotNull(r => r.DoSomething());
There's nothing built-in, but you could wrap it all up in an extension method if you wanted (although I probably wouldn't bother).
For this specific example:
string trimmed = input.NullSafeTrim();
// ...
public static class StringExtensions
{
public static string NullSafeTrim(this string source)
{
if (source == null)
return source; // or return an empty string if you prefer
return source.Trim();
}
}
Or a more general-purpose version:
string trimmed = input.IfNotNull(s => s.Trim());
// ...
public static class YourExtensions
{
public static TResult IfNotNull<TSource, TResult>(
this TSource source, Func<TSource, TResult> func)
{
if (func == null)
throw new ArgumentNullException("func");
if (source == null)
return source;
return func(source);
}
}
I had the same problem I wrote a few little extension methods:
public static TResult WhenNotNull<T, TResult>(
this T subject,
Func<T, TResult> expression)
where T : class
{
if (subject == null) return default(TResult);
return expression(subject);
}
public static TResult WhenNotNull<T, TResult>(
this T subject, Func<T, TResult> expression,
TResult defaultValue)
where T : class
{
if (subject == null) return defaultValue;
return expression(subject);
}
public static void WhenNotNull<T>(this T subject, Action<T> expression)
where T : class
{
if (subject != null)
{
expression(subject);
}
}
You use it like this;
string str = null;
return str.WhenNotNull(x => x.Length);
or
IEnumerable<object> list;
return list.FirstOrDefault().WhenNotNull(x => x.id, -1);
or
object obj;
IOptionalStuff optional = obj as IOptionalStuff;
optional.WhenNotNull(x => x.Do());
There are also overloads for nullable types.
I know this was already answered by Jon Skeet but this example might be a little more clear example of the Elvis operator ?. (aka the null-conditional member access operator)
string? someValue = (input == null) ? null : input.Trim()
is equivalent to...
string? someValue = input?.Trim();
"Thank You, Thank You Very Much" - Elvis Presley