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
Related
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));
Ok, So I'm felling super lazy and I was wondering if I can call a function dynamically by a function pointer or something else somehow?
Instead of writing a bunch of if else I can put all possible functions in an array and pass which index I wan't to execute.
I was thinking of some sort of linkedlist.
eg.
//mainClass
private void initFunctionLL()
{
currNode.functionRef = this.funct1;
...
nextNode.functionRef = this.funct2;
}
private void callNext(){
currNode = currNode.Next();
currNode.execute();
}
//
//nodeClass
public void execute()
{
call myFunctionRef();
}
If your functions has the same return type and the same parameters list then you can use Func<T> or Action to make a set of delegates to this functions and call it. Example for functions without parameters which don't return a value:
private void ExecuteManyFunctions()
{
List<Action> actions = new List<Action>();
actions.Add(Foo);
actions.Add(Bar);
foreach(var func in actions)
func();
}
private void Foo() => { // some logic here }
private void Bar() => { // some logic here }
Another example for functions with integer parameter returns string:
private void ExecuteManyFunctions()
{
List<Func<string, int>> actions = new List<Func<string, int>>();
actions.Add(Foo);
actions.Add(Bar);
var results = new List<string>();
foreach(var func in actions)
results.Add(func(1));
}
private string Foo(int x) => { return x.ToString(); }
private string Bar(int y) => { return "staticResult"; }
You can add a bunch of Func or Action delegates to a list and then call each one. If your method takes no arguments and returns nothing, then use Action, if it takes one argument and returns nothing then use Action<T> wherein T specifies the type of argument. If it returns something then use Func<T>, wherein T specifies the return type. In Func<T> the last item specifies the return type and the ones before specify the argument types. Please see links at then end of my answer for more details. There are many Action and Func delegates with variable parameters. If none of them are satisfy your needs, then look into Delegate.
For example, in example below I am declaring a list which will hold a bunch of funcs which take one int and return one int. Then I am looping through and calling each one. First one multiplies the number passed to it and return the product, while the 2nd one adds the number to itself.
var funcs = new List<Func<int, int>>();
funcs.Add(x => x * x);
funcs.Add(x => x + x);
funcs.Add(x => Square(x)); // Or like this
foreach (var thisFunc in funcs)
{
thisFunc(5);
}
private static int Square(int number)
{
return number * number;
}
Please see Func and Action.
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");
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.
Is there a way of passing in a method to a function as a parameter and then calling it via list.Sort()? I've tried this:
public static string BuildHumanSitemap(Func<TreeNode, TreeNode, int> sortMethod, params string[] classNames)
{
//calling list sort on method passed as parameter
nodes.sort(sortMethod);
}
Where the functions i want to pass in all take the same params e.g.
private static int SortByDateCreated(TreeNode x, TreeNode y)
{
DateTime xT = (DateTime)x["DocumentCreatedWhen"];
DateTime yT = (DateTime)y["DocumentCreatedWhen"];
return xT.CompareTo(yT);
}
I've also tried using an Action delegate type but the sort method complains when i pass it as a parameter. Can anyone offer a suggestion on how to do this?
Thankyou
Create new Comparison delegate and pass it to Sort method:
nodes.Sort(new Comparison<TreeNode>(sortMethod));
Maybe instead of taking in a Func<,,> delegate, you should consume a Comparison<> delegate. Because that's what List<> wants (for historical reasons; the List<>.Sort method was written for .NET 2.0, before the Func delegates were introduced).
Therefore:
public static string BuildHumanSitemap(Comparison<TreeNode> sortMethod, params string[] classNames)
{
//calling list sort on method passed as parameter
nodes.Sort(sortMethod);
}
Then call your method very simply like this:
BuildHumanSitemap(SortByDateCreated);
where SortByDateCreated is the "method group" from your question.
There's no need for first creating a delegate instance of type Func<TreeNode, TreeNode, int> and then create another delegate instance (of type Comparison<TreeNode>) which references the first one.
Of course you can also call your BuildHumanSitemap method with a lambda arrow as the first argument.
It works this way:
TreeView.TreeViewNodeSorter = new CustomNodeSorter();
private class CustomNodeSorter : IComparer
{
public int Compare(object x, object y)
{
DateTime xT = (DateTime)x["DocumentCreatedWhen"];
DateTime yT = (DateTime)y["DocumentCreatedWhen"];
return xT.CompareTo(yT);
}
}
Solution with IComparer<T>.
Comparer
public class MyTreeNodeComparer : IComparer<TreeNode>
{
public int Compare(TreeNode x, TreeNode y)
{
DateTime xT = (DateTime)x["DocumentCreatedWhen"];
DateTime yT = (DateTime)y["DocumentCreatedWhen"];
return xT.CompareTo(yT);
}
}
Usage
list.Sort(new MyTreeNodeComparer());