I have the following linq statement:
List<Type> allTypes = group.GetTypes().Union(group2.GetTypes()).ToList();
There might be a case when group2 is null which will throw me NullReferenceException
One way to solve this is to perform null check before, something like:
if (group2 != null)
{
List<Type> allTypes = group.GetTypes().Union(group2.GetTypes()).ToList();
}
else
{
List<Type> allTypes = group.GetTypes();
}
but the problem is that I have many similar assignment for different types and don't want to do if statements for each of them in such a way, but I'd rather put null check in one line, something like:
List<Type> allTypes = group.GetTypes().Union((if group2 != null)group2.GetTypes()).ToList();
but not sure how to do it with linq.
The problem you have here is not TSource being null; it's the object you want to get source from is null (group2).
You can always use Enumerable.Empty to save your magic one liners.
List<Type> allTypes = group.GetTypes().Union(group2 != null ? group2.GetTypes() : Enumerable.Empty<Type>()).ToList();
Or you can use a reusable Union overload:
public static IEnumerable<T> Union<T>(this IEnumerable<IEnumerable<T>> source)
{
var set = new HashSet<T>();
foreach (var s in source)
{
foreach (var item in s)
{
if (set.Add(item))
yield return item;
}
}
}
Then your code turns to:
var allTypes = new [] { group, group2 }.Where(x => x != null).Select(x => x.GetTypes()).Union().ToList();
The advantage of this approach is that you can have more than two sequences forming a union.
All you need here is a method to get the types of a group that can support a null parameter, since yours doesn't. It's a pretty simple method to write:
public static IEnumerable<Type> MyGetTypes(Group group)
{
if(group == null)
return Enumerable.Empty<Type>();
else
return group.GetTypes();
}
(You can make it an extension method if you want)
You can now write your original code as:
var allTypes = MyGetTypes(group).Union(MyGetTypes(group2)).ToList();
We could also generalize this instead of making this method so specific, if we wanted.
public static TResult Use<TSource, TResult>(TSource source,
Func<TSource, TResult> selector,
TResult defaultValue = default(TResult))
{
if (source == null)
return defaultValue;
else
return selector(source);
}
This would let us write:
var allTypes = group.GetTypes()
.Union(group2.Use(g => g.GetTypes(), Enumerable.Empty<Type>()))
.ToList();
When C# 6.0 comes out and we get access to the ?. operator you'd also be able to write the code out like so:
var allTypes = group.GetTypes()
.Union(group2?.GetTypes() ?? Enumerable.Empty<Type>())
.ToList();
This allows the null group to propagate to a null collection of types, rather than throwing, and then allows that null value to be substituted with an empty collection, which Union will support. This operator is more or less a built in version of our Use method, but it allows us to avoid needing to use a lambda, making it noticeably more concise.
The best I've found for putting a null check in one line is the ternary operator.
List<Type> allTypes = group2 == null ?
group.GetTypes()
: group.GetTypes().Union(group2.GetTypes()).ToList();
For this kind of situation, I typically create a new extension method. E.g.:
public static IEnumerable<T> SafeUnion<T>(
this IEnumerable<T> source1, IEnumerable<T> source2)
{
return source1 != null ?
(source2 != null ? source1.Union(source2) : source1) : source2;
}
Or whatever specific logic makes the most sense in your case (the above will allow either enumerable to be null...you might want to allow only the second, for example).
Some curmudgeons may feel that the OP is incapable of adapting this idea to his own needs. I think he probably would have no trouble, and without declarations for the variables I can't show precisely what that would look like. But it would be something a bit like this:
public static List<Type> SafeUnion(this Group group1, Group group2)
{
return (group2 != null ?
group1.GetTypes().Union(group2.GetTypes()) : group1.GetTypes();
}
Of course, the Group type needs to be replaced by whatever the type of those variables actually is. This example also doesn't allow group1 to be null. If that's required, presumably the reader can figure that change out on their own.
Related
I have a method
AddOrUpdateList(this List<T> list, T scope, Func<T, bool>, Func<T, bool> when = null){
T item = default;
if (when == null)
list.SingleOrDefault(t => t.Equals(scope)); //Check Single
else
item = list.SingleOrDefault(when);
.
.
.
}
When I'm going to use it I have two possible starts:
I receive an element which element.Title is something, so I use the Title as filter
I receive an element which has no title, so I need to get the last one from a List
I was thinking to use terniary operator and lambda to create a filter that contemplates both cases.
What I came up with is:
var filter = (element.Title != "")
? (Func<T, bool>)(e => e.Title == element.Title)
: (Func<T, bool>)(e = list.Select(ele => ele).Last());
But that gives me: Error CS0030 Cannot convert type 'T' to 'System.Func<T, bool>'
Any idea or help you can give me??
Im pretty new to C# and Linq so I don't understand to well how some things should work
Thanks in advance.
Your current filter is
var filter = (element.Title != "")
? (Func<T, bool>)(e => e.Title == element.Title)
: (Func<T, bool>)(e = list.Select(ele => ele).Last());
But e = list.Select(ele => ele).Last() is not a Func<T, bool>. In fact, it is not a function at all. As #canton7 said, you need to use the arrow notation (=>)to create a lambda. Moreover, even if that line was a lambda, it would be of type Func<T, T>,
since it simply returns the last item in a list of items of type T; it does not return a bool at all!
Is this more what you want?
var filter = (element.Title != "")
? (Func<T, bool>)(e => e.Title == element.Title)
: (Func<T, bool>)(e => e.Title == list.Last().Title);
What type of element? So, AddOrUpdateList(Func<T, bool>) uses T as type of some generic code. When you have concrete element, you should know what type of code. And set a concrete class name.
If you show more code, I will try to help you.
May be I сlimbing out of business, but it seems strange. Acording to method name, you want to Add element if it is not exist or update it if it already in list.
So, here is an example of typicaly such method implementation.
public void AddOrUpdate<T, K>(this List<T> list, T element, Func<T, K> keySelector, Action<T, T> mapFunction) : T new()
{
var elementKey = keySelector(element);
var elementForUpdate = list.FirstOrDefault(x => keySelector(x) == elementKey);
var exists = elementForUpdate != null;
if (!exists)
{
var newElement = new T();
list.Add(newElement);
elementForUpdate = list.Last();
}
mapFunction(elementForUpdate, element);
}
So, then in other part of code you can use it like:
...
var itemToAdd = new ClassWithTitle { Title = "Title 1"};
list.AddOrUpdate(itemToAdd , x => x.Title, (destination, origin) =>
{
//Logic to map fields
destination.Title = origin.Title;
destination.SomeOtherField = origin.SomeOtherField;
})
...
Please, pay attention.
One more option, if you work with list (not with database), you can use method IndexOf() then this method will very simple.
public void AddOrUpdate<T, K>(this List<T> list, T element, Func<T, K> keySelector)
{
var elementKey = keySelector(element);
var elementFounded = list.FirstOrDefault(x => keySelector(x) == elementKey);
var exists = elementForUpdate != null;
if (!exists)
{
//IMPORTANT: Here you add element that sended to method. You should take it into consideration.
//If you want to add a clone of this object, implement interface IClonable and use this method like list.Add(element.Clone());
list.Add(element);
return;
}
var indexOfFoundedElement = list.IndexOf(elementFounded);
//IMPORTANT: Here you replace element that sended to method. You should take it into consideration.
list[indexOfFoundedElement] = element;
}
My application has a method that caches a value. I need a second method that check if the generic parameter of type T implements IEnumerable and not implements IList. If the answer is yes, the method should do a .ToList and cast it back to T (See comment in code example).
Can you tell me how I do the .ToList() to return a List casted to back to T? (Is it actually possible?)
Something like this:
public T ToListIfIEnumerable<T>(T value)
{
var needToCovert = TypeImplementsGenericIEnumerableButNotGenericIList(value);
if (!needToCovert)
{
return value;
}
// return value.ToList() <-- How to do that???
}
private bool TypeImplementsGenericIEnumerableButNotGenericIList<T>(T value)
{
var type = value.GetType();
var interfaces = type.GetInterfaces();
var gi = typeof(IEnumerable<>);
var gl = typeof(IList<>);
// It would be better if the next lines did't compare strings!
// Suggestions welcome...
var implementsIEnumerable = interfaces.Any(
i => i.IsGenericType && i.Name == gi.Name && i.Namespace == gi.Namespace);
var implementsIList = interfaces.Any(
i => i.IsGenericType && i.Name == gl.Name && i.Namespace == gl.Namespace);
return implementsIEnumerable && !implementsIList;
}
Backgrond info:
The object that uses the method does something like Lazy. Caching an IEnumerable makes not much sense in examples like: Enumerable.Range(1, 3).Select(i => Guid.NewGuid()) It does gives new Guid's every time you call it. That is why I would like to do a ToList().
Dynamic typing and overloading could help here, if you don't mind using dynamic:
object ConvertToListIfNecessary(dynamic input)
{
return MaybeToList(input);
}
private IList<T> MaybeToList<T>(IEnumerable<T> input)
{
return input.ToList();
}
private IList<T> MaybeToList<T>(IList<T> input)
{
return input;
}
private object MaybeToList(object input)
{
// Take whatever action you want if the input *doesn't* implement
// IEnumerable<T>
}
Basically this gets the smarts behind dynamic to do the grungy reflection work for you. It may not be quite as quick as something that's hand-rolled, but it's likely to be much simpler to get right.
I have class "A" which has a collection of class "B". "D" is a subclass of "B" with the property "DMatter" (not inherited from "B")
I can select "A"s that have a "D" with certain content like this with regular Linq:
var result =
Aset.Where(a => a.Bs.OfType<D>().Any(d => d.DMatter.Contains("ii"))); //works!
I can dynamically on B's properties like so:
var result = Aset.Where("Bs.Any(BStuff.Contains(\"bb\"))");//works!
But I can't find a way to something like this:
result = Aset.Where("Bs.OfType<D>().Any(DMatter.Contains(\"ii\"))");//Explodes!
Any solutions?
This functionality (Cast and OfType) is now implemented in System.Linq.Dynamic.Core.
See the api documentation: OfType
Looking through the code of System.Linq.Dynamic.ExpressionParser, it seems that there is no OfType parsing implemented unfortunately. Refer this article about it, where workaround is provided as IQueryable extension methods. It seems it is the most you can get without deep dive into System.Linq.Dynamic.ExpressionParser source.
public static class MyQueryExtensions
{
public static IQueryable OfType(this IQueryable source, string typeStr)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (typeStr == null)
{
throw new ArgumentNullException("typeStr");
}
Type type = Assembly.GetExecutingAssembly().GetType(typeStr);
MethodInfo methodOfType = typeof(Queryable).GetMethods().First(m => m.Name == "OfType" && m.IsGenericMethod);
return source.Provider.CreateQuery(Expression.Call(null, methodOfType.MakeGenericMethod(new Type[] { type }), new Expression[] { source.Expression }));
}
}
and then you can:
var result = someList.OfType("SomeNamespace.SomeClass");
I have a method in my project that repeats over and over:
public PAC PAC_GetByCodiPac(string codiPac)
{
var sel = _gam.PAC.Where(pac => pac.CODI_PAC == codiPac);
if (sel.Count() > 0)
return sel.First();
return null;
}
The table PAC means (patient), so I have these methods for all the tables I have.
How can I make a generic method for this?
Thanks in advance.
Here is your generic method. Note, that as others pointed out FirstOrDefault is better than count and then first, so I'm using it here. But it's also possible to write the expression so that it mimics what your original code does. Please let me know if you need additional help with this.
public static T GetByCodi<T>(IQueryable<T> table, string codi, string fieldName) where T : class
{
// x
ParameterExpression parameter = Expression.Parameter(typeof(T), "x");
Expression currentExpression = parameter;
Type currentType = typeof(T);
PropertyInfo property = currentType.GetProperty(fieldName);
// x.CODI_xxx
currentExpression = Expression.Property(currentExpression, property);
// x.CODI_xxx == codi
currentExpression = Expression.Equal(currentExpression, Expression.Constant(codi));
// x => x.CODI_xxx == codi
LambdaExpression lambdaExpression = Expression.Lambda(currentExpression, parameter);
return table.FirstOrDefault((Func<T, bool>)lambdaExpression.Compile());
}
You use it like this:
PAC xxx = GetByCodi<PAC>(_gam.PAC, codiPac, "CODI_PAC");
Edit 1:
I changed the code according to the comment so that you can pass arbitrary ID field name in.
I see that what you asked is a very straight forward where query even doesn't require to have have it on a separate method.
Also you can simply enhance your query link the following:
public PAC PAC_GetByCodiPac(string codiPac)
{
return _gam.PAC.FirstOrDefault(pac => pac.CODI_PAC == codiPac);
}
FirstOrDefault will return the first item on the array, if not it will return null.
If you want a generic method that lets you specify any table and any predicate for records from that table then you can't really get any better than the built-in Where<T>(...) and (as others have already pointed out) the FirstOrDefault<T>(...) extension methods.
Your code would then look like so:
var result = _gam.PAC.Where(pac => pac.CODI_PAC == codiPac).FirstOrDefault();
// OR
var result = _gam.PAC.FirstOrDefault(pac => pac.CODI_PAC == codiPac);
The best you could get then, writing your own generic method, would be this:
public T FirstOrDefault<T>(IQueryable<T> source,
Expression<Func<T, bool>> predicate)
{
return source.Where(predicate).FirstOrDefault();
// OR
// return source.FirstOrDefault(predicate);
}
And that is really just redundant. Especially when your calling code would be actually longer using the helper method:
var result = FirstOrDefault(_gam.PAC, pac => pac.CODI_PAC == codiPac);
// versus
var result = _gam.PAC.FirstOrDefault(pac => pac.CODI_PAC == codiPac);
And even worse, your code is no longer using a fluent, composable syntax. This just makes readability and maintenance more difficult.
If you stick with using the IQueryable<T> extension methods then you can do composition like this:
var result = _gam.PAC
.Where(pac => pac.CODI_PAC == codiPac)
.Where(pac => pac.SomeOtherProperty == someOtherValue)
.FirstOrDefault();
// OR
var result = (from pac in _gam.PAC
where pac.CODI_PAC == codiPac
where pac.SomeOtherProperty == someOtherValue
select pac).FirstOrDefault();
One very important thing to note here is that the predicate parameter in the IQueryable<T>.Where<T>(...) extension method is of type Expression<Func<T, bool>>. This allows the IQueryable<T> provider to construct the native SQL (or other native provider query) at the very last moment before returning a result.
Not using Expression<Func<T, bool>> means that your query would be the equivalent of this:
var result =
_gam.PAC
.ToArray()
.Where(pac => pac.CODI_PAC == codiPac)
.FirstOrDefault();
And that would mean the query will load every record from the "PAC" table into memory before selecting the first filtered result and throwing out the rest of the results.
The bottom-line is that by making a generic helper method you are rewriting existing framework code and you open yourself to performance and maintenance issues while also reducing code readability.
I hope this helps.
I'm not sure if you are asking for this, but this method could be in a static class and method and so you'd be able to call it from everywhere.
An easy solution will be:
//a generic method
private PAC PAC_GetPAC(Func<PAC, bool> predicate)
{
return _gam.PAC.Where(predicate).FirstOrDefault();
}
public PAC PAC_GetPACById(long id)
{
return PAC_GetPAC(p => p.ID == id);
}
public PAC PAC_GetByCodiPac(string codiPac)
{
return PAC_GetPAC(p => pac.CODI_PAC == codiPac);
}
C#6 Update
In C#6 ?. is now a language feature:
// C#1-5
propertyValue1 = myObject != null ? myObject.StringProperty : null;
// C#6
propertyValue1 = myObject?.StringProperty;
The question below still applies to older versions, but if developing a new application using the new ?. operator is far better practice.
Original Question:
I regularly want to access properties on possibly null objects:
string propertyValue1 = null;
if( myObject1 != null )
propertyValue1 = myObject1.StringProperty;
int propertyValue2 = 0;
if( myObject2 != null )
propertyValue2 = myObject2.IntProperty;
And so on...
I use this so often that I have a snippet for it.
You can shorten this to some extent with an inline if:
propertyValue1 = myObject != null ? myObject.StringProperty : null;
However this is a little clunky, especially if setting lots of properties or if more than one level can be null, for instance:
propertyValue1 = myObject != null ?
(myObject.ObjectProp != null ? myObject.ObjectProp.StringProperty) : null : null;
What I really want is ?? style syntax, which works great for directly null types:
int? i = SomeFunctionWhichMightReturnNull();
propertyValue2 = i ?? 0;
So I came up with the following:
public static TResult IfNotNull<T, TResult>( this T input, Func<T, TResult> action, TResult valueIfNull )
where T : class
{
if ( input != null ) return action( input );
else return valueIfNull;
}
//lets us have a null default if the type is nullable
public static TResult IfNotNull<T, TResult>( this T input, Func<T, TResult> action )
where T : class
where TResult : class
{ return input.IfNotNull( action, null ); }
This lets me us this syntax:
propertyValue1 = myObject1.IfNotNull( x => x.StringProperty );
propertyValue2 = myObject2.IfNotNull( x => x.IntProperty, 0);
//or one with multiple levels
propertyValue1 = myObject.IfNotNull(
o => o.ObjectProp.IfNotNull( p => p.StringProperty ) );
This simplifies these calls, but I'm not sure about checking this sort of extension method in - it does make the code a little easier to read, but at the cost of extending object. This would appear on everything, although I could put it in a specifically referenced namespace.
This example is a rather simple one, a slightly more complex one would be comparing two nullable object properties:
if( ( obj1 == null && obj2 == null ) ||
( obj1 != null && obj2 != null && obj1.Property == obj2.Property ) )
...
//becomes
if( obj1.NullCompare( obj2, (x,y) => x.Property == y.Property )
...
What are the pitfalls of using extensions in this way? Are other coders likely to be confused? Is this just abuse of extensions?
I guess what I really want here is a compiler/language extension:
propertyValue1 = myObject != null ? myObject.StringProperty : null;
//becomes
propertyValue1 = myObject?StringProperty;
This would make the complex case far easier:
propertyValue1 = myObject != null ?
(myObject.ObjectProp != null ? myObject.ObjectProp.StringProperty) : null
//becomes
propertyValue1 = myObject?ObjectProp?StringProperty;
This would only work for value types, but you could return nullable equivalents:
int? propertyValue2 = myObject?ObjectProp?IntProperty;
//or
int propertyValue3 = myObject?ObjectProp?IntProperty ?? 0;
We independently came up with the exact same extension method name and implementation: Null-propagating extension method. So we don't think it's confusing or an abuse of extension methods.
I would write your "multiple levels" example with chaining as follows:
propertyValue1 = myObject.IfNotNull(o => o.ObjectProp).IfNotNull(p => p.StringProperty);
There's a now-closed bug on Microsoft Connect that proposed "?." as a new C# operator that would perform this null propagation. Mads Torgersen (from the C# language team) briefly explained why they won't implement it.
Here's another solution, for chained members, including extension methods:
public static U PropagateNulls<T,U> ( this T obj
,Expression<Func<T,U>> expr)
{ if (obj==null) return default(U);
//uses a stack to reverse Member1(Member2(obj)) to obj.Member1.Member2
var members = new Stack<MemberInfo>();
bool searchingForMembers = true;
Expression currentExpression = expr.Body;
while (searchingForMembers) switch (currentExpression.NodeType)
{ case ExpressionType.Parameter: searchingForMembers = false; break;
case ExpressionType.MemberAccess:
{ var ma= (MemberExpression) currentExpression;
members.Push(ma.Member);
currentExpression = ma.Expression;
} break;
case ExpressionType.Call:
{ var mc = (MethodCallExpression) currentExpression;
members.Push(mc.Method);
//only supports 1-arg static methods and 0-arg instance methods
if ( (mc.Method.IsStatic && mc.Arguments.Count == 1)
|| (mc.Arguments.Count == 0))
{ currentExpression = mc.Method.IsStatic ? mc.Arguments[0]
: mc.Object;
break;
}
throw new NotSupportedException(mc.Method+" is not supported");
}
default: throw new NotSupportedException
(currentExpression.GetType()+" not supported");
}
object currValue = obj;
while(members.Count > 0)
{ var m = members.Pop();
switch(m.MemberType)
{ case MemberTypes.Field:
currValue = ((FieldInfo) m).GetValue(currValue);
break;
case MemberTypes.Method:
var method = (MethodBase) m;
currValue = method.IsStatic
? method.Invoke(null,new[]{currValue})
: method.Invoke(currValue,null);
break;
case MemberTypes.Property:
var method = ((PropertyInfo) m).GetGetMethod(true);
currValue = method.Invoke(currValue,null);
break;
}
if (currValue==null) return default(U);
}
return (U) currValue;
}
Then you can do this where any can be null, or none:
foo.PropagateNulls(x => x.ExtensionMethod().Property.Field.Method());
If you find yourself having to check very often if a reference to an object is null, may be you should be using the Null Object Pattern. In this pattern, instead of using null to deal with the case where you don't have an object, you implement a new class with the same interface but with methods and properties that return adequate default values.
How is
propertyValue1 = myObject.IfNotNull(o => o.ObjectProp.IfNotNull( p => p.StringProperty ) );
easier to read and write than
if(myObject != null && myObject.ObjectProp != null)
propertyValue1 = myObject.ObjectProp.StringProperty;
Jafar Husain posted a sample of using Expression Trees to check for null in a chain, Runtime macros in C# 3.
This obviously has performance implications though. Now if only we had a way to do this at compile time.
I just have to say that I love this hack!
I hadn't realized that extension methods don't imply a null check, but it totally makes sense. As James pointed out, The extension method call itself is not any more expensive than a normal method, however if you are doing a ton of this, then it does make sense to follow the Null Object Pattern, that ljorquera suggested. Or to use a null object and ?? together.
class Class1
{
public static readonly Class1 Empty = new Class1();
.
.
x = (obj1 ?? Class1.Empty).X;
it does make the code a little easier to read, but at the cost of extending object. This would appear on everything,
Note that you are not actually extending anything (except theoretically).
propertyValue2 = myObject2.IfNotNull( x => x.IntProperty, 0);
will generate IL code exactly as if it were written:
ExtentionClass::IfNotNull(myObject2, x => x.IntProperty, 0);
There is no "overhead" added to the objects to support this.
To reader not in the know it looks like you're calling a method on a null reference. If you want this, I'd suggest putting it in a utility class rather than using an extension method:
propertyValue1 = Util.IfNotNull(myObject1, x => x.StringProperty );
propertyValue2 = Util.IfNotNull(myObject2, x => x.IntProperty, 0);
The "Util." grates, but is IMO the lesser syntactic evil.
Also, if you developing this as part of a team, then gently ask what others think and do. Consistency across a codebase for frequently used patterns is important.
While extension methods generally cause misunderstandings when called from null instances, I think the intent is pretty straightforward in this case.
string x = null;
int len = x.IfNotNull(y => y.Length, 0);
I would want to be sure this static method works on Value Types that can be null, such as int?
Edit: compiler says that neither of these are valid:
public void Test()
{
int? x = null;
int a = x.IfNotNull(z => z.Value + 1, 3);
int b = x.IfNotNull(z => z.Value + 1);
}
Other than that, go for it.
Not an answer to the exact question asked, but there is Null-Conditional Operator in C# 6.0. I can argue it will be a poor choice to use the option in OP since C# 6.0 :)
So your expression is simpler,
string propertyValue = myObject?.StringProperty;
In case myObject is null it returns null. In case the property is a value type you have to use equivalent nullable type, like,
int? propertyValue = myObject?.IntProperty;
Or otherwise you can coalesce with null coalescing operator to give a default value in case of null. For eg,
int propertyValue = myObject?.IntProperty ?? 0;
?. is not the only syntax available. For indexed properties you can use ?[..]. For eg,
string propertyValue = myObject?[index]; //returns null in case myObject is null
One surprising behaviour of the ?. operator is that it can intelligently bypass subsequent .Member calls if object happens to be null. One such example is given in the link:
var result = value?.Substring(0, Math.Min(value.Length, length)).PadRight(length);
In this case result is null if value is null and value.Length expression wouldn't result in NullReferenceException.
Personally, even after all your explanation, I can't remember how the heck this works:
if( obj1.NullCompare( obj2, (x,y) => x.Property == y.Property )
This could be because I have no C# experience; however, I could read and understand everything else in your code. I prefer to keep code language agnostic (esp. for trivial things) so that tomorrow, another developer could change it to a whole new language without too much information about the existing language.
Here is another solution using myObject.NullSafe(x=>x.SomeProperty.NullSafe(x=>x.SomeMethod)), explained at
http://www.epitka.blogspot.com/