Func<> with lambda expression - c#

I have found following part of code in some examples while learning Func<> syntax:
public static class Lambda
{
public static int MyFunc(Func<string, int> func)
{
//some logic
return 0;
}
}
And sample call :
var getInt = Lambda.MyFunc((url) => { Console.WriteLine(url); return 0; }
And My Question :
Why passing above func as lambda expression with this (url) is allowed if value is never assigned ( or maybe is ?)?
What is the point of passing Func like this ?
Edit :
To clarify my question . I was only wondering about this sample call - why passing string as argument like above (using lambda (url) => {} ) is not forbidden by compiler if the value can not be initiated. Is there any example that can be useful with passing string like above ?

url is the name of the parameter for the lambda expression. It's like writing a method like this:
public static int Foo(string url)
{
Console.WriteLine(url);
return 0;
}
Then creating a delegate from it:
Func<string, int> func = Foo;
Now in order to call the delegate, you need to provide it a string - and that then becomes the value of the parameter, just like if you called the method normally:
int result = func("some url");

Related

How to use Func when you require access to its parameter at invoke?

I have a dictionary that contains a string as a key, and a function to run when said string has been discovered. It then passes in the object used that was discovered. I merely want access to this object within the function body, but am unsure how to do it. I presume the lambda operator has to be used, but i don't really know how to properly use it.
public Dictionary<string, Func<object, bool>> stringReceivedRegister;
My setup
string received_name = StringFormater.GetName(receivedMessage);
object changed_string = openMethod.Invoke(instance, new object[] { receivedMessage });
StringTypes.Instance.stringReceivedRegister[received_name].Invoke(changed_string);
When adding a function to the stringReceivedRegister how would i access it within the function i pass in?
StringTypes.Instance.stringReceivedRegister.Add("Test", function where i can get access to 'changed string');
To add a function to stringReceivedRegister, your first need to declare a method:
private static bool MyFunction(object x) {
// ...
}
And then you can pass MyFunction to Add:
// Note the absence of () after "MyFunction". I am not actually calling it
stringReceivedRegister.Add("Test", MyFunction);
The x parameter will refer to changed_string when you do this:
StringTypes.Instance.stringReceivedRegister[received_name].Invoke(changed_string);
It's quite annoying to have to declare a method very time, so C# 3 provided lambda expressions, allowing you to do this:
stringReceivedRegister.Add("Test", x => {
// ...
});
Again, x will refer to changed_string when you invoke the delegate with changed_string.
Look at this code:
static bool FunctionTest(object o) {
return true;
}
static void Main(string[] args) {
Dictionary<string, Func<object, bool>> dict = new Dictonary<string, Func<object, bool>>();
dict.Add("A", ((obj) => { return false; }));
dict.Add("B", FunctionTest);
Console.WriteLine(dict["A"](1));
Console.WriteLine(dict["B"](1));

How to get all parameters from an Action type variable

I need to build a trace that can log all parameters passed in a Action code variable.
How to get all parameters from the Action instance, considering that the action variable is filled with a lambda expression?
Updated (clarifying the use of action object)
I post below the API tracer that i am trying to build. The API tracer need to get parameters from lambda expressions passed in the action object:
public static class Tracer
{
public static void log(Action action)
{
// note that action will always be set with a lambda function. See ServiceProxy class bellow.
//..grab the action parameters and name and log them
}
}
I only found ways to get these kind of information from expressions. From action type object, i don't find were it holds the parameters, only found the method name.
This Tracer is to use in a Proxy class that exposes an service. All calls should be logged. The Proxy uses an function wrapper that calls the service, like this:
class ServiceProxy:IServiceProxy {
...
private void CallWrapper(Action func)
{
try
{
Tracer.log(func);
func();
}
catch (Exception ex){...}
}
//method call example
public void IServiceProxy.RequestX(String p1, int p2){
CallWrapper(() => service.RequestX(p1, p2));//p1 and p2 parametersshould be logged by the Tracer.
}
}
In order to reuse the CallWrapper method, the lambda expression signature must be dynamic, this means func type can't be declared as an generic (ex:Action<String,Int>).
You can extract your arguments with Linq.Expressions.
This mean you need to change Action to Expression<Action>.
Aftre doing that you will be capable to go through your lambda with custom expression visitor.
So lets start by adding a new class that would be inspect your expression:
public class ArgumentExtractor : System.Linq.Expressions.ExpressionVisitor
{
private Dictionary<string, object> arguments;
public IDictionary<string, object> Arguments => arguments;
protected override Expression VisitMethodCall(MethodCallExpression node)
{
arguments = node.Arguments
.Select(a =>
{
var memeber = a as MemberExpression;
if (memeber == null)
return null;
var name = memeber.Member.Name;
var container = (memeber.Expression as ConstantExpression)?.Value;
var value = container.GetType().GetField(name).GetValue(container);
return new {name, value};
})
.Where(x => x != null)
.ToDictionary(x => x.name, x => x.value);
return base.VisitMethodCall(node);
}
}
Now we can use it in your Tracer:
public static class Tracer
{
public static void log(Expression<Action> action)
{
var argumentExtractor = new ArgumentExtractor();
argumentExtractor.Visit(action);
var arguments = argumentExtractor.Arguments;
// to do: write it to log
}
}
Finaly we need to modify CallWrapper:
private static void CallWrapper(Expression<Action> func)
{
Tracer.log(func);
func.Compile().Invoke();
}
You can find full demo here

Lambda expression "=>"

I'm trying to understand a code but I can't understand what 'p' var is.
public Prediction(Game kkk,bool checkit, params State[] checkStates)
: base(game, p => Manager.method(kkk, p))
{
this.checkit = checkit;
this.checkStates = checkStates;
}
The second class:
public PiratePrediction(Game game, System.Func<Pirate, T> valueExtractor)
{
this.game = game;
this.valueExtractor = valueExtractor;
this.predictedValues = new Dictionary<Pirate, T>();
this.totalPredictions = 0;
this.correctPredictions = 0;
}
found the class you're using on https://github.com/YoavKa/Skillz2016/blob/f23d25eed4baa9786cf517583ee867075a2f0505/API/Prediction/PiratePrediction.cs
the valueExtractor lambda is used from Update, and p comes from the keys of predictedValues dictionary.
public virtual void Update()
{
foreach (var pair in this.predictedValues)
{
if (pair.Key.State != PirateState.Lost && !EqualityComparer<T>.Default.Equals(pair.Value, default(T)))
{
this.totalPredictions++;
if (this.valueExtractor(pair.Key).Equals(pair.Value))
this.correctPredictions++;
}
}
this.predictedValues.Clear();
}
the p comes from the call to Predict method of PiratePrediction class. Because it's added to the predictedValues array.
public T Predict(Pirate p)
{
if (this.predictedValues.ContainsKey(p))
return this.predictedValues[p];
T predictedValue = this.predict(p);
if (EqualityComparer<T>.Default.Equals(predictedValue, default(T)))
return default(T);
this.predictedValues.Add(p, predictedValue);
return predictedValue;
}
p is a parameter being passed into your method. A Func<T, TOut> is a delegate, meaning a method signature.
Consider the following:
private class DisplayClass
{
public readonly Game kkk;
public DisplayyClass(Game kkk) { this.kkk = kkk; }
public T handler(Pirate p) { return Manager.method(kkk, p); }
}
public Prediction(Game kkk,bool checkit, params State[] checkStates)
: base(game, new DisplayClass(kkk).handler)
{
this.checkit= checkit;
this.checkStates = checkStates;
}
This is what the compiler does to your code when interpreting lambdas - it may be a good idea to pass your code through a decompiler to see the exact phrasing.
The p variable, as you can see in the expanded code, is a parameter into the method, and lambdas are just a shorthand way to pass methods which can then be invoked in other code.
// Somewhere in the base class...
void ExtractValue(Pirate p)
{
// ...
T value = this.valueExtractor(p);
// ...
}
When thus invoked, p will be the value passed in by that other code, and by definition of Func<Pirate, T>, will be of type Pirate.
Keep in mind that the code you're passing a lambda to can invoke the code inside your lambda multiple times, such as is the case with .Select. I suggest not only reading up on lambdas, but also their extensive use in the Linq namespace
A lambda expression is a declaration of an anonymous method. So imagine that this:
p => Manager.method(kkk, p)
is equal to this:
private T SomeMethod<T>(Pirate p)
{
return Manager.method(kkk, p);
}
You wouldn't be able to do the second snippet in your situation, however, because kkk is a local variable from the scope of where the lambda expression was declared, which means that while the lambda can use kkk, an explicit method declaration can't (See Closure). This is just one benefit of lambdas over declared methods.

Get the boolean from Func<T, bool>

I want to get the boolean value from the following fluent function:
public IGridWithOptions<T> CursorPointerWhen(Func<T, bool> propertySpecifier)
{
bool r = ????
return this;
}
How can this be done ?
You can call like a method in your class, since you have the first T argument, for sample:
T argument = /* get a instance of generic T argument */;
bool r = propertySpecifier(argument);
You'll need to have a T value in order to call the delegate:
public IGridWithOptions<T> CursorPointerWhen(Func<T, bool> propertySpecifier)
{
T input = GetInputFromSomewhere();
bool r = propertySpecifier(input);
// ...
return this;
}
It's impossible to do this without a T. For example, consider this:
Func<string, bool> longString = x => x.Length > 100;
What is the "value" of that? It only makes any sense in the context of a particular string. We don't have much information about what you're trying to do here, but you'll need to get an instance of T from somewhere - or change your method argument.

Passing a Function (with parameters) as a parameter?

I want to create a generic to which I can pass a function as a parameter, however this function may include parameters itself so...
int foo = GetCachedValue("LastFoo", methodToGetFoo)
Such that:
protected int methodToGetFoo(DateTime today)
{ return 2; // example only }
Essentially I want to have a method that will check the cache for a value, otherwise will generate the value based on the passed in method.
Thoughts?
It sounds like you want a Func<T>:
T GetCachedValue<T>(string key, Func<T> method) {
T value;
if(!cache.TryGetValue(key, out value)) {
value = method();
cache[key] = value;
}
return value;
}
The caller can then wrap this in many ways; for simple functions:
int i = GetCachedValue("Foo", GetNextValue);
...
int GetNextValue() {...}
or where arguments are involved, a closure:
var bar = ...
int i = GetCachedValue("Foo", () => GetNextValue(bar));
Use System.Action and a lambda expression (anonymous method). For example:
public void myMethod(int integer) {
// Do something
}
public void passFunction(System.Action methodWithParameters) {
// Invoke
methodWithParameters();
}
// ...
// Pass anonymous method using lambda expression
passFunction(() => myMethod(1234));
You can create your own delegate, but in C# 3.0 you may find it more convenient to use the built-in Func<T> delegate family to solve this problem. Example:
public int GetCachedValue(string p1, int p2,
Func<DateTime, int> getCachedValue)
{
// do some stuff in here
// you can call getCachedValue like any normal function from within here
}
This method will take three arguments: a string, an int, and a function that takes a DateTime and returns an int. For example:
int foo = GetCachedValue("blah", 5, methodToGetFoo); // using your method
int bar = GetCachedValue("fuzz", 1, d => d.TotalDays); // using a lambda
Different Func<T, U, V...> etc. types exist in the framework to accommodate methods with different amounts of arguments.
Create a delegate for the method methodToGetFoo
public delegate object GenerateValue(params p);
public event GenerateValue OnGenerateValue;
Define GetCachedValue to use the delegate
int GetCachedValue(string key, GenerateValue functionToCall);
Then in the implementation of OnGenerateValue you can check the param's.
Here is something simple I started that can be taken a bit further (as I did for a commercial project).
In my case this was to cache web service calls, and was used something like:
WebService ws = new WebService();
var result = ws.Call( x => x.Foo("bar", 1)); // x is the ws instance

Categories

Resources