I need to understand how a developer can make use of Action delegates and lambdas. I will give an example:
For example, using MOQ, you write something like:
var repoMock = new Mock<IMyInterface>();
repoMock.Setup(r => r.GetData()).Returns(new string[] {"one", "two", "three"});
My point is, how's the code inside "Setup" and "Returns" is making use of the input (lambda expression)?
If you look at the type signatures for the Moq methods, you will notice that Setup and Returns are actually doing to very different things. Returns takes a delegate (a Func<TResult> or a Func<T, TResult>), but Setup actually takes an Expression, which is a much more complex data type. More details about the difference between Func<T> (a delegate) and Expression<Func<T>> (an expression) can be found in this related answer. The rest of my answer will try to explain how Moq, specifically, uses those two different types for two different reasons. Hopefully that will at least get you started in how to use them in your own code.
Delegates, whether they be named, anonymous, or lambda expressions, are .NET's way of permitting functions to be used as a "first class" objects; that's just a fancy way of saying that delegates can be used in all the same ways that the primitive types: you can declare local delegates, pass delegates as parameters, and return delegates from methods. You "call" a delegate the same way you call any other function: you use the () syntax.
In your case, you used the overload of Returns that doesn't actually take a delegate, it simply takes an value that will be returned whenever the associated mocked method is called. However, there are overloads of Returns that do take delegates, so you could have equivalently written this:
.Returns(() => new string[] {"one", "two", "three"}};
or
.Returns(x => x.produceStringArray("one", "two", "three"));
In either case, the Returns method will be given a delegate, of the appropriate type, as a parameter. Internally, all Returns really does is to save the delegate as part of the mocked object instance. Later, when the mocked method gets called, the delegate is executed to return the correct value. While the real Moq internals are more complex that this, the basic idea is something like the following:
private Func<T> returnMe;
public void Returns<T>(Func<T> myDelegate)
{
this.returnMe = myDelegate;
}
public T Execute()
{
return this.returnMe();
}
As you can see, once you have a delegate, you can just call it like any other function; when the compiler sees a lambda expression somewhere that it expects a delegate, it compiles the lambda expression into an anonymous delegate and that's what gets passed into your method.
The Setup method, on the other hand, is far more complex. The lambda expression there is not being passed as a Func<T>, but as an Expression<Func<T>>. What this means is, the compiler is not compiling the lambda expression into a delegate, but rather, into an expression tree. The objects in an expression tree are special types of object that represent the various things that a method can do. Compilers produce expression trees out of your source code all the time, but usually those expression trees are immediately used to produce machine code. When the C# compiler compiles an Expression, however, it actually leaves the expression tree in it's "half-compiled" state. You can finish compiling an expression, and run the resulting code if you want, but that's not the only way they are used. Your program can also examine the expression tree and see all the details about what the code "would do" if it were compiled and run, and use that information however it wants.
When you call a Moq method like this:
moq.Setup(x => x.MyMethod(1, 2, 3)).Returns(true);
the Setup method can use the expression tree to figure out the name of the method, and the types and values of the parameters, that you wrote on the right-hand side of your lambda. In this case, Moq never executes your lambda expression, merely examines it. It creates an internal object that is associated with the specific method call you just set up, and records the various things you associate with that method (e.g. the Return calls.) Later on, when you use your mocked object in a unit test, Moq will intercept every method call you make on your object, and scan its list of set-up methods looking for one that matches the call, and produce whatever mocked-up behavior you've specified about that call.
It is like the Setup method calls (or stores a reference to, for future use) a method with parameter "r" which returns r.GetData() value.
Related
I have this:
myObj.SetupSomething(It.IsAny<string>());
then in MyObj class:
public void SetupSomething(string s)
{
_someMock.Setup(c => c.DoWibble(s));
}
The above code does not work work, because It.IsAny<> comes through as null so it sets it up with null instead of any string. If I replace it with this:
_someMock.Setup(c => c.DoWibble(It.IsAny<string>()));
Then it works ok. So I'm wondering, can I pass the expression of It.IsAny<string>() through to my method so that Moq still recognises what I'm doing, or do I need to make an extra SetupSomethingForAnyString() method (which is kinda nasty)?
As you discovered, the short answer is 'No', it's not possible to just pass a raw It.IsAny<string>() result as a parameter to a setup. But that's not really the end of the story. There's some incredible nuance to how Moq detects expression arguments and transforms them into matchers that are ultimately used when providing return values during actual execution. If you have the time, I definitely recommend taking a peek into the source. There's some cool gymnastics happening there-- and it's not just expression tree analysis.
At the most basic level, the reason that using It.IsAny<string>() as a parameter outside of a setup doesn't work has to do with the order of execution. Consider:
var x = It.IsAny<string>();
mock.Setup(m => m.DoWibble(x));
vs
mock.Setup(m => m.DoWibble(It.IsAny<string>()));
It the first, It.IsAny<string>() is evaluated outside of any mock context, and outside of the mock context, the library can't really return a meaningful value, so it just returns default(T). That null value is then bound as a variable which is captured in the quoted lambda expression, m => m.DoWibble(x).
That whole expression is passed to the Setup method, and the Moq library will partially evaluate the expressions provided for the arguments, including the captured value, 'x'. The current value is default(string), so it will set up a matcher that will only work if the null value is passed.
In the second, the quoted expression now includes the entire m => m.DoWibble(It.IsAny<string>()) call. Now when Moq partially executes It.IsAny<string>(), it's in a context where it can cooperate with an observer to perform side-effects, informing the Moq library to create the 'any' matcher for that argument.
But that means that Moq can detect a call to It.IsAny methods even if it's not directly invoked as part of the original quoted lambda. That means that this works as well:
Func<string> callIsAny = () => It.IsAny<string>();
mock.Setup(m => m.DoWibble(callIsAny.Invoke()));
The key here is that It.IsAny<string>() isn't actually invoked in the statement prior to the setup, but instead is only evaluted while Moq is analyzing the arguments to the mocked method. And because it sets up a detection context to see when It.IsAny is invoked, it can correctly create the matcher for this case.
Note that this isn't documented anywhere in the Moq usage guidelines, so I'm not sure if the fact that this works is intended. The detection context for It.IsAny is likely only intended to be there for setting up event handlers. But it's certainly cool, though!
Instead, if you want to actually pass argument matchers through some layer of indirection, it seems best to utilize the feature already present in Moq: It.Is.
It would be defined as:
public void SetupSomething(Expression<Func<string, bool>> stringMatcher)
{
_someMock.Setup(m => m.DoWibble(It.Is(stringMatcher)));
}
Used like:
myObj.SetupSomething(_ => true); // match anything
myObj.SetupSomething(s => s == "a"); // match only calls with "a";
It's not as readable as using the normal It.IsAny call, but you could alleviate that by including your own matcher lambda as a property or method call (e.g., Match.Any<string>())
At that point, it seems rather like re-implementing the domain language of Moq though. It's up to you if it's worth the effort.
For a test, I want to create a generic "helper" method which will take take two arguments, the first argument is a function (or a reference to the function) and the 2nd argument is a list of objects for that function that are to be called as its parameters.
The following does this perfectly:
CallMyFunctionWithParamsPlease(new Func<int, int>(MyMethod), new object[] {1});
public static int CallMyFunctionWithParamsPlease(Delegate func, params object[] args)
{
func.DynamicInvoke(args);
return 3;
}
The thing is, this doesn't look very nice when calling it and I wish to abstract it into another method to act as syntatic sugar.
Ideally I want it to be called like this:
CallMyFunctionWithParamsPlease(myMethod, new Object[] {1});
From what I can gather, there is no elegant solution to do this in C# since I cannot pass myMethod by itself as a reference anywhere, instead I must pass it by declaring a new Func along with the return type of the method. Since I'm not using this return type anywhere, I'm not sure why it's necessary to input this information. My limited understanding is that because C# is statically typed, the compiler must know everything and things like this just aren't possible.
Is this true or not? How would I create syntatic sugar to simply pass a method to another method which can be called there without needing to invoke "new Func"? I would have thought simply passing the function as a reference pointer would allow me to do this, but I'm having difficultly doing this too. I looked into delegates, using "unsafe" with pointers, and a few other options. None of them seem to make this possible, or if they do, they didn't explain it in a manner that I could understand.
I simply want to pass a method to another method, and invoke it with a variable list of object params with variable length whereby I don't need to specify this whilst invoking it. I'm not sure if I'm trying to force C# to do something it's not meant to do here, and instead I'd be better off using a dynamically typed language to do this. The problem is I really enjoy the intellisense that the static typing of C# offers, along with the performance improvements over a language like Python. I'd just like a way to syntactically abstract away the boilerplate with my own helper methods for things like this.
UPDATE: Thanks to the comments here it seems I can do this with a lambda expression nice and elegantly. The signature can be simply changed to public static long CallMyFunctionWithParamsPlease<T>(Func<T> func)
If deferred execution is what you want simply pass a Func<TReturnType> to your method (or class). The calling method doesn't need to know how many parameters are involved.
e.g. Assuming MyMethod has a signature int MyMethod(int arg):
CallMyFunctionWithParamsPlease(() => MyMethod(1));
public static int CallMyFunctionWithParamsPlease(Func<int> func)
{
return func();
}
If MyMethod takes two parameters, it's the same call:
CallMyFunctionWithParamsPlease(() => MyMethod(1, 2));
What's it called when a method that takes a lambda expression as the parameter, such as Enumerable.Where, is invoked without actually declaring a variable or method parameter in the expression?
For example, I'm familiar with this lambda expression syntax:
public string GetDigits(string input)
{
return new String(input.Where(i => Char.IsDigit(i)).ToArray());
}
However, I was surprised to find out that this can also be written as:
public string GetDigits(string input)
{
return new String(input.Where(Char.IsDigit).ToArray());
}
What's going on in that second snippet, where the Char.IsDigit() method is (apparently) being called with an implicit parameter? What is this syntax called?
Methods don't accept lambdas as parameters. They accept delegates as parameters. A lambda is just one way of creating a delegate.
Another way is supplying a method group, as is done in your second example, which can be converted to a delegate.
A similar way is to use the anonymous method feature. This was more or less replaced with lambdas when they were added though, so you don't see it much. Your example using that syntax would be:
Func<char, bool> predicate = delegate(char c) { return Char.IsDigit(c); };
Yet another way would be to create a delegate using Delegate.CreateDelegate. (This isn't something you see all that often though.)
A final way is to have a delegate variable that you got from somewhere else. (That somewhere else would have created the delegate using one of these other options.)
What's going on in that second snippet, where the Char.IsDigit() method is (apparently) being called with an implicit parameter? What is this syntax called?
It's not being called. That's the whole point. We're trying to create a delegate. A delegate is an object that keeps track of a method to be invoked, and an object that it should be invoked on. You can then invoke the delegate and it will call the method that was used to create it. So here you're not calling IsDigit, you're creating a delegate that is pointing to the IsDigit method, and that will call it whenever that delegate is invoked.
When you use a lambda you're creating a new method, possibly in a new class, (neither of which have a name you can refer to, but they'll have one at runtime) and the body of that anonymous method will call IsDigit. The lambda then resolves to a delegate pointing to that anonymous method, which maintains the semantics of the other example of having a method that when called, calls an anonymous method which, in its implementation, calls IsDigit. It's adding an extra layer of indirection (that may or may not just get optimized out at runtime) to accomplish the same thing.
The signature of Enumerable.Where is:
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate
)
This:
input.Where(i => Char.IsDigit(i))
is equivalent to writing:
Func<char, bool> temp = i => Char.IsDigit(i);
input.Where(temp);
so it creates an anonymous function with a parameter i that calls Char.IsDigit.
This:
input.Where(Char.IsDigit)
is equivalent to
Func<char, bool> temp = Char.IsDigit;
input.Where(temp);
that is equivalent to:
Func<char, bool> temp = new Func<char, bool>(Char.IsDigit);
input.Where(temp);
so it creates a delegate to Char.IsDigit and then passes it to input.Where.
So the second one removes the "man-in-the-middle" (the anonymous function). In this particular case it is "legal" because the i parameter of the anonymous function is passed "as is" to Char.IsDigit. It would have been different if it was:
input.Where(i => !Char.IsDigit(i))
in this case, you can't remove the man-in-the-middle (the anonymous function).
There is no name for all of this (or you could call the first "creating and passing a delegate to an anonymous function" and the second "creating and passing a delegate created from a method group"... but they aren't beautiful catchphrases, they are more a description of what you are doing)
Because the compiler will implicitly cast the method group to a delegate if it finds a single method that matches the expected signature, in this case a delegate taking a single char as input and returning a bool.
Your Where expects a Func<char, bool>, which is a delegate for methods that take a char argument and return a bool. Anything that matches this delegate is a valid argument for this Where.
The lambda you wrote initially matches this delegate by type inference: the compiler expects that i is char, based on the generic parameter of the enumerable source - and infers the return type as bool, because that's what the method call expression inside the lambda would return.
The Char.IsDigit method itself also matches this. Thus, referencing the method is another valid way of expressing the same thing. This is called a method group.
The semantic equivalence of these two possible arguments for Where also makes sense if you consider that for every lambda expression, the compiler generates an anonymous method and then passes that anonymous method where the delegate was expected.
To illustrate this, consider your original snippet:
Where(i => Char.IsDigit(i))
The above gets lowered by the compiler to:
bool AnAnonymousMethod(char i)
{
return Char.IsDigit(i);
}
and then:
Where(AnAnonymousMethod)
As you can see, the lambda syntax (in cases where you don't have captured variables, like here) is just syntactic sugar for writing an anonymous method and then using the method group of this newly written method as the argument wherever a compatible delegate is expected.
I'm looking to get hold of a method name from a lambda expression, I'm aware it can be done this way:
GetName(() => MethodA());
My issue is that if MethodA takes any args, you have to supply them just to satisfy the compiler about the expression (after all, how can it know you're not actually executing it?)
I'd like to be able to do:
GetName(() => MethodA);
Is there a way of doing this?
NOTE: This is not a duplicate, this is dealing with a Method Group and not an actual "invocation" of a method.
Certainly. If you have your GetName method take an Expression<Func<Action>> as a parameter, for example, then you can pass () => MethodA into it, as long as MethodA is convertible to the same delegate signature as Action.
void Main()
{
Expression<Func<Action>> x = () => Foo;
Expression<Func<Func<int>>> y = () => Foo2;
var xName = ((MethodInfo)((ConstantExpression)((MethodCallExpression)((UnaryExpression)x.Body).Operand).Object).Value).Name;
}
void Foo(){}
int Foo2(){return 0;}
You can write your GetName method to examine the given expression and extract out the name of the method group from it. However, there are two things you should keep in mind.
Even if your lambda expression appears to "call" a method, it's only an expression and won't actually generate a call to that method.
Trying to capture a method group this way will make it very difficult to distinguish between overloaded methods with the same name.
For that reason, I have to imagine you'd be better off using a more traditional approach that does involve a method call expression.
For the case, of a void-returning parameterless method, the signature of GetName could look like this:
string GetName(Expression<Func<Action>> methodExpression)
That Action in there is a problem, to make it work for methods with other signatures, you would need to add lots of overloads for other delegate types.
A solution to this is to make GetName generic and let the user specify the delegate type:
string GetName<T>(Expression<Func<T>> methodExpression)
…
GetName<Action>(() => MethodA)
The problem with this approach is that T can be any type, not just a delegate, so it's very easy to call this version of GetName incorrectly, especially since GetName(() => MethodB()) will often compile (specifically, when MethodB returns something), due to type inference.
And type constrains won't help you here, you can't write where T : Delegate.
With the advent of new features like lambda expressions (inline code), does it mean we dont have to use delegates or anonymous methods anymore? In almost all the samples I have seen, it is for rewriting using the new syntax.
Any place where we still have to use delegates and lambda expressions won't work?
Yes there are places where directly using anonymous delegates and lambda expressions won't work.
If a method takes an untyped Delegate then the compiler doesn't know what to resolve the anonymous delegate/lambda expression to and you will get a compiler error.
public static void Invoke(Delegate d)
{
d.DynamicInvoke();
}
static void Main(string[] args)
{
// fails
Invoke(() => Console.WriteLine("Test"));
// works
Invoke(new Action(() => Console.WriteLine("Test")));
Console.ReadKey();
}
The failing line of code will get the compiler error "Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type".
lambda is shortcut for anonymous delegate, but you will always be using delegates. the delegate specifies the methods signature. you can just do this:
delegate(int i) { Console.WriteLine(i.ToString()) }
can be replaced with
f => Console.WriteLine(f.ToString())
Lambda expression is not (and was not meant to be) a silver bullet that would replace (hide) delegates. It is great with small local things like:
List<string> names = GetNames();
names.ForEach(Console.WriteLine);
it makes code more readable thus simple to understand.
It makes code shorter thus less work for us ;)
On the other hand it is very simple to misuse them. Long or/and complex lambda expressions are tending to be:
Hard to understand for new developers
Less object oriented
Much harder to read
So “does it mean we don’t have to use delegates or anonymous methods anymore?” No – use Lambda expression where you win time/readability otherwise consider using delegates.
One not so big advantage for the older delegate syntax is that you need not specify the parameters if you dont use it in the method body. From msdn
There is one case in which an anonymous method provides functionality
not found in lambda expressions. Anonymous methods enable you to omit
the parameter list. This means that an anonymous method can be
converted to delegates with a variety of signatures. This is not
possible with lambda expressions.
For example you can do:
Action<int> a = delegate { }; //takes 1 argument, but not specified on the RHS
While this fails:
Action<int> a = => { }; //omitted parameter, doesnt compile.
This technique mostly comes handy when writing event-handlers, like:
button.onClicked += delegate { Console.WriteLine("clicked"); };
This is not a strong advantage. It's better to adopt the newer syntax always imho.
Delegate have two meanings in C#.
The keyword delegate can be used to define a function signature type. This is usually used when defininge the signature of higher-order functions, i.e. functions that take other functions as arguments. This use of delegate is still relevant.
The delegate keyword can also be used to define an inline anonymous function. In the case where the function is just a single expression, the lambda syntax is a simpler alternative.
Lambda expressions are just "syntactic sugar", the compiler will generate appropriate delegates for you. You can investigate this by using Lutz Roeder's Reflector.
Lamda's are just syntactic sugar for delegates, they are not just inline, you can do the following:
s.Find(a =>
{
if (a.StartsWith("H"))
return a.Equals("HI");
else
return !a.Equals("FOO");
});
And delegates are still used when defining events, or when you have lots of arguments and want to actually strongly type the method being called.