I have a get-only property in C# that returns an IEnumerable. If that property will only ever yield once, then I could define my property like so:
public IEnumerable Derp {
get { yield return new SomeObject(); }
}
But how would I do this with a C#6 expression-bodied member? The following approaches do NOT work:
// These definitions do NOT work
public IEnumerable Derp => yield return new SomeObject();
public IEnumerable Derp => yield new SomeObject();
returning compiler error CS0103: "The name 'yield' does not exist in the current context". Is a yielding expression-bodied member even possible in C#6? How about in C#7?
I'm aware that an IEnumerable member that only returns once looks smelly, but I'm mainly just curious. I came across this situation while experimenting with the NUnit TestCaseSource API, trying to provide a method that yields only one test case. I could also see this being relevant to Unity developers who want to define an expression-bodied method to be called with StartCoroutine().
Anyway, thanks in advance for your thoughts!
Expression-bodied functions/properties can't have statements... You can't, for example:
static int Test(int x) => if (x > 0) x else 0;
or even
static int Test(int x) => return x;
yield is a statement... You can't use it :-)
Note that you can:
IEnumerable<SomeObject> Derp => new[] { new SomeObject() };
From the Roslyn github page, New Language Features in C# 6:
2.1 Expression bodies on method-like members
Methods as well as user-defined operators and conversions can be given an expression body by use of the “lambda arrow”:
The effect is exactly the same as if the methods had had a block body with a single return statement.
For void returning methods – and Task returning async methods – the arrow syntax still applies, but the
expression following the arrow must be a statement expression (just as is the rule for lambdas):
So there is an exception for void returning methods, but still it only covers calling methods (you can => Console.WriteLine("Hello"); but you can't => if ()).
Related
I have an object list and I can add record with that sentence:
List<DragerClass.Alarm> alarms = new List<DragerClass.Alarm>();
public void createAlarm(int i, int[] alarms)
{
alarms.Add(new DragerClass.Alarm(i, DateTime.Now, DragerClass.Dedector.Dedector_Name[i] + " UNDER RANGE"))`;
}
But when I try to remove an item, it behaves like lambda expression doesn't support:
public void removeAlarm(int i)
{
alarms.Remove(x => x.Dedector_No == i);
}
I see that message when I stand on the code
cannot convert lambda expression to type
'Drager_GasDedection.DragerClass.Alarm' because it is not a delegate
type
I'm using Visual Studio 2010 and I also added System.Data.Entity in references. But still same. Thanks for any help.
Take a look at the methods of List<T>. The method Remove(T) simply expects one element. If it is found in the list it is removed, otherwise nothing is done. Remove is not looking for a Predicate<T> that it will check.
RemoveAll(Predicate<T>) however expects a predicate. So you need to call:
alarms.RemoveAll(x => x.Dedector_No == i);
You also have to change = to == in your code since otherwise you are performing an assignment instead of an equality check. Furthermore note that the method will remove all alarms with the given detector number, not just the first.
I have a situation where I need to assign some objects' properties inside an object initializer. Some of these objects can be null and I need to access their properties, the problem is that they are too many, and using a if/else thing is not good.
Example
visits = visitJoins.AsEnumerable().Select(joined => new VisitPDV()
{
VisiteId = joined.Visite.VisiteId.ToString(),
NomPointDeVente = joined.VisitePdvProduit.PointDeVente.NomPointDeVente,
});
The joined.VisitePdvProduit can be null, and the problem is that there are like dozens of such assignments (I just took one to shorten the code)
The C# 6 Null-Conditional operator is the perfect solution for this situation, the problem is that I'm on C# 5 in this project, is there a way to imitate that ?
Well, you can use an extension method that receives an accessor delegate and only executes it if the item isn't null:
public static TResult ConditionalAccess<TItem, TResult>(this TItem item, Func<TItem, TResult> accessor) where TResult : Class
{
if (item == null)
{
return null;
}
else
{
return accessor(item);
}
}
You can use it for example like this:
NomPointDeVente = joined.VisitePdvProduit.ConditionalAccess(_ => _.PointDeVente.NomPointDeVente);
You can easily create versions of this method for operations that don't return a value (i.e. bar.ConditionalAccess(_ => _.Foo())) or return value types.
Like this. Ugly, but what had to be done.
visits = visitJoins.AsEnumerable().Select(joined => new VisitPDV()
{
VisiteId = joined.Visite.VisiteId.ToString(),
NomPointDeVente = (joined.VisitePdvProduit == null) ? null : joined.VisitePdvProduit.PointDeVente.NomPointDeVente,
});
If you are talking about the semi-very surprised operator ?., then no. There's no way to mimic the syntax.
What you can do, though, is to create an extension method (or a helper method, static one, preferably) or an instance method working with the properties.
Or, as someone suggested, just use the conditional statement (inline or explicit). But that's not what you're looking for, of course.
One more method (and it's not at all recommendable) is to surround the assignment with a try-catch. But that's really baaad solution and I only mention it for completeness' sake.
I have this code (the whole code is not important but can be seen on this link):
internal static class PlayCardActionValidator
{
public static bool CanPlayCard(...)
{
// ...
var hasBigger =
playerCards.Any(
c => c.Suit == otherPlayerCard.Suit
&& c.GetValue() > otherPlayerCard.GetValue());
// ...
}
}
After opening the code in decompiler (ILSpy) for example I noticed the existence of newly created class <>c__DisplayClass0_0 by the C# compiler:
This wouldn't be a problem for me if this code wasn't critical for the performance of the system. This method is called millions of times and the garbage collector is cleaning these <>c__DisplayClass0_0 instances which slows down the performance:
How can I avoid creating this class (his instances and their garbage collecting) when using the Any method?
Why does the C# compiler create this class and is there any alternative of Any() I can use?
To understand the "display class" you have to understand closures. The lambda you pass here is a closure, a special type of method that magically drags in state from the scope of the method it's in and "closes around" it.
...except of course that there's no such thing as magic. All that state has to actually live somewhere real, somewhere that's associated with the closure method and readily available from it. And what do you call the programming pattern where you associate state directly with one or more methods?
That's right: classes. The compiler transforms the lambda into a closure class, then instantiates the class inside the hosting method so the hosting method can access the state in the class.
The only way to not have this happen is to not use closures. If this is really impacting performance, use an old-school FOR loop instead of a LINQ expression.
How can I avoid creating this class (his instances and their garbage collecting) when using the Any method?
Why does the C# compiler creates this class and is there any alternative of Any() I can use?
Other posters already explained the why part, so the better question would be How can I avoid creation of a closure?. And the answer is simple: if lambda is using only the passed parameters and/or constants, the compiler will not create a closure. For instance:
bool AnyClub() { return playerCards.Any(c => c.Suit == CardSuit.Club); }
bool AnyOf(CardSuit suit) { return playerCards.Any(c => c.Suit == suit); }
The first will not create a closure while the second will.
With all that in mind, and assuming you don't want to use for/foreach loops, you can create own extension methods similar to those in System.Linq.Enumerable but with additional parameters. For this particular case, something like this would work:
public static class Extensions
{
public static bool Any<T, TArg>(this IEnumerable<T> source, TArg arg, Func<T, TArg, bool> predicate)
{
foreach (var item in source)
if (predicate(item, arg)) return true;
return false;
}
}
and change the code in question to:
var hasBigger =
playerCards.Any(otherPlayerCard,
(c, opc) => c.Suit == opc.Suit
&& c.GetValue() > opc.GetValue());
I have a helper method which gets the name of a property defined by a lambda which works as below:
ExpressionUtil.GetName((Thing t) => t.Property); // returns "Property"
I would like to turn this into an extension method so the syntax would be of the form:
((Thing t) => t.Property).GetName(); // wont compile : operator '.' cannot be applies to operand of type 'lambda expression'
However I cant seem to do this as ((Thing t) => t.Property) is a lambda (not an expression or Func yet). Is there any way to write an extension method which applies directly to a lambda? If not why is this a bad thing to do?
You can't do that, because a lambda expression has no type by itself; its type is determined by the context (e.g. if you assign it to a delegate variable or pass it as an argument to a method).
Since ((Thing t) => t.Property) doesn't have a type, you can't call an extension method on it, because the compiler doesn't know which extension methods are valid candidates.
You can, however, declare a variable and call the extension method on it:
Func<Thing, OtherThing> func = t => t.Property;
string name = func.GetName();
you may create an extension method on an Action at the low cost of having a introducing instantiation.
I sometimes use it and the code is readable.
The reason this code exists is less elegant, a rotten NAS :-[
new Action(() =>
{
if (File.Exists(newFullPath))
File.Delete(newFullPath);
File.Move(oldFullPath, newFullPath);
})
.Try(attemps: 2, exceptionValidator: (exception, attempt, attempts) =>
{
var throwIt = (attempt == attempts);
if (!throwIt)
Thread.Sleep(500);
// .. tracing ./. throw
return (throwIt);
});
Just in case ... even if post not young.
Question: I have just wrote my first code using c# lambda expressions. It works, but I am not sure if this is the best way to do it. Any recommendations on a better way to do the lambda expression? It seems odd to have numerous lines of code in the expression like I do below.
Background: I have a generic list of delegates. Each delegate function returns an enum value indicating what happened in the function. Upon evaluation of the delegate, I need to add the enum to a List if it was not a specific enum value.
Disclaimer: Code here is very generic, the real code actually does stuff in the delegates to determine the return value!
class Class1
{
public enum WhatHappened
{
ThingA,
ThingB,
Nothing
}
private delegate WhatHappened del();
public static List<WhatHappened> DoStuff()
{
List<del> CheckValues = new List<del>();
List<WhatHappened> returnValue = new List<WhatHappened> { };
CheckValues.Add(delegate { return method1(); });
CheckValues.Add(delegate { return method2(); });
CheckValues.ForEach(x =>
{
WhatHappened wh = x();
if (wh != WhatHappened.Nothing)
returnValue.Add(wh);
});
return returnValue;
}
private static WhatHappened method1()
{
return WhatHappened.Nothing;
}
private static WhatHappened method2()
{
return WhatHappened.ThingA;
}
}
Note: I originally had the lambda like adding all the items (see below), then removing the ones I didn't want (WhatHappened.Nothing).
CheckValues.ForEach(x => returnValue.Add(x()));
Okay, a few suggestions:
Don't call your delegate del. In this case, I'd use Func<WhatHappened> - but if you do want to declare your own delegate type, give it a more descriptive name, and obey the .NET naming conventions.
Instead of using anonymous methods to add to CheckValues, you can just use:
CheckValues.Add(method1);
CheckValues.Add(method2);
The compiler will convert the method groups into delegates.
I'd recommend not using Pascal case for a local variable name to start with.
Your collection initializer for returnValues isn't really doing anything for you - just call the List<T> constructor as normal, or use my code below which doesn't require a local variable to start with.
If your list really only has two delegates in it, I'd just call them separately. It's a lot simpler.
Otherwise you can indeed use LINQ as Jared suggests, but I'd do it slightly differently:
return CheckValues.Select(x => x())
.Where(wh => wh != WhatHappened.Nothing)
.ToList();
EDIT: As suggested, here's the full example. It's not quite the same as Denis's though... I've made a couple of changes :)
public static List<WhatHappened> DoStuff()
{
var functions = new List<Func<WhatHappened>> { Method1, Method2 };
return functions.Select(function => function())
.Where(result => result != WhatHappened.Nothing)
.ToList();
}
(I'm assuming that method1 and method2 have been renamed to fit the naming convention. Of course in real life I'm sure they'd have more useful names anyway...)
I would simply use Linq, but that's just me:
public static List<WhatHappened> DoStuff()
{
List<del> CheckValues = new List<del>();
List<WhatHappened> returnValue = new List<WhatHappened>();
CheckValues.Add(method1);
CheckValues.Add(method2);
return CheckValues
.Select(dlg => dlg())
.Where( res => res != WhatHappened.Nothing)
.ToList();
}
Note that you can also use Func instead of declaring a Delegate type if you want, but that's less terse in that case.
Also, I'd return an IEnumerable<WhatHappened> instead of a List, but it's all about the context.
You can go lambda all the way by chaining Select (map) and Where (filter) instead of multiple FOR loops and IF statements
// get results from the list of functions
var results = CheckValues.Select(x => x());
// filter out only the relevant ones.
var returnValues = results.Where(x => x != WhatHappened.Nothing);
Basically, you should think more declaratively instead of imperatively when work ing with lambdas. It'll help you write more elegant code.
It's a bit more idiomatic to write the following instead of using the delegate keyword. It doesn't change the underlying functionality though.
CheckValues.Add( () => method1() );
Also, I find it more readable to rewrite the ForEach as the following
CheckValues = CheckValues.
Select(x => x()).
Where(wh => wh != WhatHappened.Nothing ).
ToList();
In my opinion, based on the example, it looks fine. You could refactor even more by replacing:
CheckValues.Add(delegate { return method1(); });
CheckValues.Add(delegate { return method2(); });
with:
CheckValues.Add(() => WhatHappened.Nothing);
CheckValues.Add(() => WhatHappened.ThingA);
Here's a LINQ-free solution:
return CheckValues
.ConvertAll<WhatHappened>(x => x())
.FindAll(y => y != WhatHappened.Nothing);
caveat
This is not the most performant solution, as it would iterate twice.
I can't fathom the purpose of the code.. however here goes.
Used delegate chaining
Update: and picked up some Enumerable goodness from Jon n Jared's posts
private delegate WhatHappened WhatHappenedDelegate();
public static List<WhatHappened> DoStuff()
{
WhatHappenedDelegate delegateChain = null;
delegateChain += method1;
delegateChain += method2;
return delegateChain.GetInvocationList()
.Select(x => (WhatHappened) x.DynamicInvoke())
.Where( wh => (wh != WhatHappened.Nothing))
.ToList<WhatHappened>();
}