I'm trying to figure out C#'s syntax for anonymous functions, and something isn't making sense to me. Why is this valid
Func<string, string> f = x => { return "Hello, world!"; };
but this isn't?
Func<string> g = { return "Hello, world!"; };
The second still requires the lambda syntax:
Func<string> g = () => { return "Hello, world!"; };
In the first, you're effectively writing:
Func<string, string> f = (x) => { return "Hello, world!"; };
But C# will let you leave off the () when defining a lambda if there is only a single argument, letting you write x => instead. When there are no arguments, you must include the ().
This is specified in section 7.15 of the C# language specification:
In an anonymous function with a single, implicitly typed parameter, the parentheses may be omitted from the parameter list. In other words, an anonymous function of the form
( param ) => expr
can be abbreviated to
param => expr
You need to know the function definition:
Encapsulates a method that has one parameter and returns a value of
the type specified by the TResult parameter.
References:
Microsoft
Related
I'm stuck on a lambda with a single int parameter and a bool return value:
Expression<Func<int, bool>> myFunc = x => x == 5;
First, I tried this that returns a new Func that I can't make sense of; I was expecting a true boolean value:
var boolResult = Expression.Lambda(myFunc).Compile().DynamicInvoke(5);
Then I tried to explictly set the function parameters and return type instead:
var param = Expression.Parameter(typeof(int), "x");
var fn = Expression.Lambda<Func<int, bool>> (myFunc, param).Compile();
, but this throws an error:
System.ArgumentException : Expression of type
'System.Func`2[System.Int32,System.Boolean]' cannot be used for return
type 'System.Boolean'
Which is weird, but I tried to convert the expression:
var fn = Expression.Lambda<Func<int, bool>> (
Expression.Convert(myFunc,
typeof(Func<int, bool>))
, param).Compile();
var boolResult = fn.Invoke(5);
, this however did not help and gives the same error:
System.ArgumentException : Expression of type
'System.Func`2[System.Int32,System.Boolean]' cannot be used for return
type 'System.Boolean'
Any idea of what I'm doing wrong here?
The error in your dynamic invocation code is the way in which you construct your lambda. When you pass myFunc as expression, you get a lambda that returns Func<int,bool>.
If you want to make a new LambdaExpression that takes int and return bool, you could harvest Body and Parameters of your myFunc object, like this:
var b = Expression.Lambda(myFunc.Body, myFunc.Parameters).Compile().DynamicInvoke(5);
or, since myFunc is already a LambdaExpression, you could compile it directly:
var c = myFunc.Compile().DynamicInvoke(6);
Demo.
TLDR: How does this compile?
class A{};
Expression<Func<A, int>> e = x => 24; // I don't understant what makes this compile
// and what happens at this assignment
What is the minimum class E to be able to compile E e = x => 24;
Some investigation
class E {};
E e = x => 24;
Visual Studio error is "Cannot convert lambda expression to type 'E' because it is not a delegate type" which is confusing because as far as I know a delegate is declared like this:
int delegate MyHandle();
and I didn't find any way of making a class a delegate.
Furthermore I have looked at the metadata of Expression -> LambdaExpression -> Expression<TDelegate> and wasn't able to identify what syntax/declaration makes Expression<TDelegate> act like a delegate.
Even more I have tried to create my own class E to mimic Expression<TDelegate> and I wasn't even able to compile the class
// basically a copy-paste of the metadata of `Expression<TDelegate>`
public sealed class E<TDelegate> : LambdaExpression
{
public TDelegate Compile() => default(TDelegate);
public TDelegate Compile(DebugInfoGenerator debugInfoGenerator) => default(TDelegate);
public TDelegate Compile(bool preferInterpretation) => default(TDelegate);
public Expression Update(Expression body, IEnumerable<ParameterExpression> parameters)
=> default(Expression);
protected override Expression Accept(ExpressionVisitor visitor) => null;
}
getting the error "'LambdaExpression' does not contain a constructor that takes 0 arguments"
Context (can be skipped):
I am getting started with Moq and because I just cannot take things for granted I am trying to understand how it works / how it is implemented. So this the first part of a series of inquiries about that.
I am now specifically trying to understand
public class A
{
public virtual int Foo() => throw new NotImplementedException();
public virtual int Bar() => throw new NotImplementedException();
}
var a = new Mock<A>();
a.Setup(x => x.Foo()).Returns(24); // ??
Console.WriteLine(a.Object.Foo());
I am trying to understand how the information "the method Foo" is passed to a
by passing that lambda? As far as I know a lambda is just a callable object, but somehow magically a knows the actual body of the lambda, i.e. will throw if you pass x => 24 or x => x.Foo() + x.Bar() but will accept x => x.Foo()
And I see that Setup parameter is of type Expression<Func<A, int>> hence my current question.
The C# specification gives special treatment to System.Linq.Expressions.Expression<D>; you cannot get the same treatment for your own type.
Expression trees permit lambda expressions to be represented as data structures instead of executable code. Expression trees are values of expression tree types of the form System.Linq.Expressions.Expression<D>, where D is any delegate type.
Source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/types#expression-tree-types
This is a Lambda expression:
x => 24
According to MSDN Lambda expressions a lambda expression can be used to create a delegate or an expression tree type.
A Func<T, int> is a delegate function that takes a T as input and returns an int as output. If you assign the lambda expression above to this Func, then the compiler assumes that the x in the lambda expression is the input of the Func, and the part after the => is the output of the Func:
Func<string, int> func = x => x.Length;
Here x is expected to be a string, the part after the => may use, but is not obliged to use, this x to produce the output which has to be an int.
Func<int, int> func = x => x = -x;
Here x is expected to be an int. The return of the function is -x which is also an int.
Expression is the base class of all kinds of expressions. Expressions represent an operation that return a value. The most basic expressions are constants, they represent just a constant value, like 24. Other expressions might be additions, which take as input two expressions and have one output value. Other expressions are multiplication, negation, etc, which return a "number", or boolean expressions like AND OR NOR etc which return a Boolean.
A special kind of expression (so a derived class) is a LambdaExpression. A LambdaExpression usually represents a function-like object: it has zero or more input parameters and one output parameter. You assign a value to a LambdaExpression using a lambda expression (note the space in lambda expression!):
Expression<Func<string, int>> myExpression = x => x.Length;
I wrote earlier what the lambda expression x => x.Length does. the statement above creates an object of type System.Linq.Expressions.Expression<TDelegate>, which is of type LambdaExpression, hence you can assign it to an Expression<Func<string, int>>.
Your question:
What is the minimum class E to be able to compile E e = x => 24?
Your class E will need a constructor (or assignment operator) that accepts a System.Linq.Expressions.Expression<Func<MyClass, int> as parameter. If you don't use the x from your lambda expression MyClass can be object
Of course it is also accepted if the constructor takes any of the base classes, like Expression. However, if you do so you won't be able to used any of the Expression<Func<MyClass, int> functionality.
About your Mock code
Apparently you have a class A with two functions Foo and Bar, and you want to instantiate a Mock object to mock the functionality of A.
var myAmock = new Mock<A>();
myAmock.Setup(x => x.Foo()).Returns(24);
This says, that myAmock is an object that should mock behaviour of class A. Whenever someone calls the Foo function it should return a value of 24.
I have a function which uses the "Any" method on a list.
List<String> list = Factory.ReturnList(); //Returns a list of all countries in Europe
I need to verify that the list contains partial strings like "(DE)" and "(FR)", ...
Assert.Equal(list.Any(item=> item.Contains("(DE)")), true);
Assert.Equal(list.Any(item=> item.Contains("(FR)")), true);
Assert.Equal(list.Any(item=> item.Contains("(BE)")), true);
Assert.Equal(list.Any(item=> item.Contains("(NL)")), true);
Now I would like to write it as a function. I have seen other people use code like this:
Func<IWebElement, bool> condition = item => item.Text == "something";
Assert.Equal(list.Any(condition), true);
I already tried the following, but that didn't work:
Func<List<String>, bool> condition = list.Any(x => x.Contains(input));
Due to:
Cannot implicitly convert type 'bool' to 'System.Func<System.Collections.Generic.List<string>, bool>'
How can I do that in my example?
'input' needs to be a parameter/variable so the Func can be invoked with different parameters
You are currently invoking the method and trying to assign it to your Func which of course doesn't work since you've already invoked it, returning bool.
Instead, encapsulate the two input arguments and update the Func signature to match your intent.
Func<List<String>, string, bool> condition =
(list, input) => list.Any(x => x.Contains(input));
You can then invoke your Func like so:
Assert.Equal(condition(new List<string>(), ""), true);
This gives you the highest degree of flexibility and reusability since the condition is constant, but the parameters can change.
If you just want a lambda expression, use:
Func<List<String>, bool> condition = (list,input) => list.Any(x => x.Contains(input));
How about putting those strings into an array?
string[] countries = { "DE", "FR", "BE", "NL" };
result = from item in list
where countries.Any(val => item.Contains(val))
select item;
I've searched a bit about type inference, but I can't seem to apply any of the solutions to my particular problem.
I'm doing a lot of work with building and passing around functions. This seems to me like it should be able to infer the int type. The only thing I can think of is that the lambda return type isn't checked by the type inference algorithm. I have stripped unnecessary logic to show the issue more clearly.
Func<T> Test<T>(Func<Func<T>> func)
{
return func();
}
this compiles:
Func<int> x = Test<int>(() =>
{
int i = 0;
return () => i;
});
but this gives the error "The type arguments for method cannot be inferred from the usage. Try specifying the type arguments explicitly":
Func<int> x = Test(() =>
{
int i = 0;
return () => i;
});
I guess I would just like to know why it works this way and any workarounds.
I would say that the correct answer to the question is given by E.Lippert in SO Why can't an anonymous method be assigned to var?
But let us play with your example a little:
Func<Func<int>> f = () =>
{
int i = 0;
return () => i;
};
Func<int> x = Test(f); //it compiles OK
No problem in type inference with your Func<T> Test<T>(Func<Func<T>> func) here.
The problem is hidden in that you use an anonymous lambda expression, the type of which cannot be inferred. Try this:
var f = () =>
{
int i = 0;
return () => i;
};
It gives Compiler Error CS0815, saying
Cannot assign lambda expression to an implicitly-typed local variable
and the explanation is:
An expression that is used as the initializer for an implicitly typed
variable must have a type. Because anonymous function expressions,
method group expressions, and the null literal expression do not have
a type, they are not appropriate initializers. An implicitly typed
variable cannot be initialized with a null value in its declaration,
although it can later be assigned a value of null.
Now let's try another thing:
var x = Test(() =>
{
Func<int> f = () => 0;
return f;
});
It compiles as well. So the problem with your original example was actually with this line:
return () => i;
We can go further and according to what Eric Lippert says in his answer provide another function to wrap this:
static Func<T> GetFunc<T>(Func<T> f) { return f; }
Now we can rewrite your code like:
var x = Test(() =>
{
int i = 0;
return GetFunc(() => i);
});
And it works as well.
However, as far as I understand, this all is an overhead and you should just provide an explicit type. While these workarounds are suitable, when you need to have a lambda, returning an object of anonymous type.
I have the following method that I can't figure out correct syntax to call:
public T GetAndProcessDependants<C>(Func<object> aquire,
Action<IEnumerable<C>, Func<C, object>> dependencyAction) {}
I'm trying to call it like this:
var obj = MyClass.GetAndProcessDependants<int>(() => DateTime.Now,
(() => someList, (id) => { return DoSomething(x); }) }
Edited:
thx everyone, you guys helped turned on a light bulb in my head. here is what i did:
var obj = MyClass.GetAndProcessDependants<int>(
() => DateTime.Now,
(list, f) =>
{
list = someList;
f = id => { return DoSomething(id); };
});
not sure why i even an issue with this. it's one of those days i guess..
thx
Your lambda syntax is totally wrong.
You need to create a single lambda expression with two parameters:
(list, id) => DoSomething(...)
Right now the function is only accepting a single argument, when it asks for two!
You need to accept a list argument, such as (list, id) => {}
Just looking at the description above, it looks like the call should be:
var obj = MyClass.GetAndProcessDependants<int>(() => DateTime.Now,
(seq, fun) => { /* do something with seq and fun */ });
The key is since you are passing an Action that takes a Func, the caller is (most likely) going to be the one passing that Func into your Action. So you just specify how that Func is applied to the sequence passed in (if I'm reading the prototype correctly).
var obj = MyClass.GetAndProcessDependants<int>(
() => DateTime.Now,
(someList, id) => DoSomething(x)
);