C#: Convert a generic function to a Func object - c#

I have the following function:
private int GetEnumTypeUnderlyingId<T>()
{
return (int)Enum.Parse(typeof(T), Enum.GetName(typeof(T), _franchise.LogonDialog));
}
I want to convert it to a Func type. I write something like:
Func<int> GetEnumTypeUnderlyingIdFunc<T> = () => (int)Enum.Parse(typeof(T), Enum.GetName(typeof(T), _franchise.LogonDialog));
But this does not work. I am not really comfortable when working with Func<>, Generics and lambda expressions so any help will be greatly appreciated

You can define your own delegate. Here is what you are looking for:
//Your function type
delegate int GetEnumTypeUnderlyingIdFunc<T>();
//An instance of your function type
GetEnumTypeUnderlyingIdFunc<int> myFunction = () => //some code to return an int ;
Also this works too.
//An instance of Func delegate
Func<int> GetEnumTypeUnderlyingIdFunc = () => //some code to return an int;

Another solution would be
public Func<int> GetTheFunc<T>(T val)
{
Func<int> func = () => (int)Enum.Parse(typeof(T),Enum.GetName(typeof(T),val));
return func;
}
Then
var func = GetTheFunc<_franchise>(_franchise.LoginDialog);
//Now you can use the func, pass it around or whatever..
var intValue = func();

Related

Lookup a lambda expression in a dictionary by a key, and then use it?

Sorry for the newbie question, but how would you:
call a dictionary with a lambda expression as the value
run that lambda expression with a variable as an argument and capture the return value.
javascript version would be like:
function LookUpAndDo(num, funcName) {
const dictionary = {
myFunc: (x) => { return x},
}
const runThis = dictionary[funcName];
return runThis(num)
}
LookUpAndDo(5, "myFunc");
// returns 5
This method is pretty straightforward to convert to C#
private T LookUpAndDo<T>(T param, string funcName)
{
var dict = new Dictionary<string, Func<T, T>>{
{ "myFunc", x => x }
};
var func = dict[funcName];
return func.Invoke(param);
}
And you may invoke it as LookUpAndDo(5, "myFunc");
In the case Func parameter and return types does not match, then you'd have to specify both types in the generic method:
private TResult LookUpAndDo<T, TResult>(T param, string funcName)
{
var dict = new Dictionary<string, Func<T, TResult>>{
{ "myFunc", x => x.ToString() }
};
var func = dict[funcName];
return func.Invoke(param);
}
And since C# can't infer return types, you'd have to call passing both type parameters, as: LookUpAndDo<int, string>(5, "myFunc");

Dynamically convert Func to corresponding Action

I'm trying to use the Convert method on functions as well as actions, so I can avoid writing duplicate methods taking in delegates of Func type. Convert method comes from Convert Action<T> to Action<object>
public class Program
{
static void Main(string[] args)
{
var program = new Program();
var mi = program.GetType().GetMethod("Function", BindingFlags.Instance | BindingFlags.Public);
// Can be any version of Func
var funcType = typeof(Func<int, int>);
// Create action delegate somehow instead
var del = mi.CreateDelegate(funcType, null);
// Or dynamically convert the Func to a corresponding Action type (in this case Action<int>)
}
// Or find a way to pass it in as a parameter here
public Action<object> Convert<T>(Action<T> action)
{
return o => action((T)o);
}
public int Function(int five)
{
return five;
}
}
I think you are looking for something like this:
public static Action<T1> IgnoreResult<T1,T2>(Func<T1,T2> func)
{
return x => func(x);
}
But for all variants of Func<T1,T2....>
I think this would work:
public static Action<TR> IgnoreResult<TR>(Delegate f)
{
return x => f.DynamicInvoke(x);
}
With usage:
var action = IgnoreResult<int>(new Func<int,int>(program.Function));
action(5);
You'll not be able to get it to infer the parameters and return type without copy and pasting the first example for all variants of Action<T1...> and Func<T1,T2...>.

Anonymous method with return

Please tell me what is wrong and how to write annonymous method with return for this impementation
public class Test
{
public string Implisity { get; set; }
}
class Program
{
static void Main(string[] args)
{
/*Here is a problem */
var variable = Method(delegate(IList<string> i, List<string> j){ return new Test(){Implisity = i[j.IndexOf("Implisity")]}; });
}
public static List<T> Method<T>(Func<IList<string>, IList<string>, T> staff) { return new List<T>(){staff(new List<string>() {"1","2"}, new List<string>(){"Explisity","Implisity"})}; }
}
this is a flat method what as me need to make annonymous
public static Test Annonymous(IList<string> i, List<string> j)
{
var obj = new Test() { Implisity = i[j.IndexOf("Implisity")] };
return obj;
}
The problem is that the Method(...) method expects a Func<...> with different parameter types: it expects a method that takes two IList<string> objects, while you are making a delegate that takes an IList<string> and a List<string>
var variable = Method(
delegate(IList<string> i, IList<string> j) {
// ^
return new Test() {
Implisity = i[j.IndexOf("Implisity")]
};
}
);
To avoid issues like this in the future, use implicit typing, like this:
var variable = Method( (i, j) => new Test { Implisity = i[j.IndexOf("Implisity")] } );
In this example, the compiler knows what the parameter types of the function must be from the signature of the Method(...) method, so it implicitly assigns the types to i and j.
Try this:
var variable = Method((i, j) => new Test() { Implisity = i[j.IndexOf("Implisity")] });
A lambda expression is an unnamed method written in place of a delegate instance.
The compiler immediately converts the lambda expression to either:
A delegate instance.
An expression tree, of type Expression<TDelegate>, representing the
code inside the lambda expression in a traversable object model. This
allows the lambda expression to be interpreted later at runtime

Can a delegate take a generic as a parameter

I've created a class that works with my cache to get cached items. If the items are not cached then it calls a function to get the actual value.
This class has eight methods, all with almost identical code except for the function they call. I've created a function called GetObject which takes a delegate to call if it can't find an item in the class.
I can't get my code to compile because of the following error:
Argument 2: cannot convert from
'System.Collections.Generic.List<string>' to
'MyFunction<System.Collections.Generic.List<string>>'.
Am I doing something wrong or am I'm trying to do something that can't be done?
Here's the code I'm trying.
public delegate T MyFunction<T>(string s);
public T GetCultures<T>(string s) where T : class {
return NewListOfStrings(s) as T;
}
public List<string> NewListOfStrings(string s) {
return new List<string> { s };
}
public List<string> GetListOfStrings(string sitename) {
string key = cachingService.CreateValidKey("stringvalue");
//This is the line that fails to compile
var foundItems = GetObject<List<string>>(key,
GetCultures<List<string>>(sitename));
return foundItems;
}
public T GetObject<T>(string key, MyFunction<T> f) where T : class {
T foundItems = (T)cachingService.GetCachedItem(key);
if (foundItems == null) {
lock (key) {
foundItems = (T)cachingService.GetCachedItem(key);
if (foundItems == null) {
foundItems = f as T;
if (foundItems != null) {
cachingService.SetCachedItem(key, foundItems, 5,
Constants.MINUTES);
}
}
}
}
return foundItems;
}
Solution
public T GetObject<T>(string key, Func<T> getFromRepository) where T : class {
T foundItems = (T)cachingService.GetCachedItem(key);
if (foundItems == null) {
lock (key) {
foundItems = (T)cachingService.GetCachedItem(key);
if (foundItems == null) {
foundItems = getFromRepository() as T;
if (foundItems != null) {
cachingService.SetCachedItem(key, foundItems, 5,
Constants.MINUTES);
}
}
}
}
return foundItems;
}
public AreaModels.Site GetSiteByName(string sitename) {
string key = cachingService.CreateValidKey(
string.Format("Site_{0}", sitename));
return GetObject<AreaModels.Site>(key,
() => efRepository.GetSiteByName(sitename));
}
public List<AreaModels.Culture> GetCulturesForSite(string sitename) {
string key = cachingService.CreateValidKey(
string.Format("Cultures_{0}", sitename));
return GetObject<List<AreaModels.Culture>>(key,
() => efRepository.GetCulturesForSite(sitename));
}
public List<AreaModels.Resource> Resources(string sitename, int appId) {
string key = cachingService.CreateValidKey(
string.Format("ResourcesFor{0}", sitename));
return GetObject<List<AreaModels.Resource>>(key,
() => efRepository.GetResourcesBySiteAndAppId(sitename, appId));
}
You're passing the result of the function rather than the function itself. You can use a lambda like so:
var foundItems = GetObject<List<string>>(key,
name => GetCultures<List<string>>(sitename));
You also have this line:
foundItems = f as T;
Here you're trying to cast the function itself to its return type, which won't work. Instead you could do:
foundItems = f(name);
But now your problem is that you'd have to pass the name into GetObject, because otherwise it won't be accessible where it's needed. The reason for this is there's a mismatch between MyFunction, which takes a string, and what you actually want, which is a function that can be evaluated within GetObject without needing the name parameter to be passed in.
So what you should really do is change your delegate to:
public delegate T MyFunction<T>();
Or alternatively get rid of the delegate altogether and have the f parameter be a Func<T>.
With either of these options, you can pass in the lamba with no parameter required:
var foundItems = GetObject<List<string>>(key,
() => GetCultures<List<string>>(sitename));
And evaluate it like:
foundItems = f();
Note that it's a bit roundabout to create a lambda to pass it into another method just to then evaluate it, rather than just passing the result in directly. So unless there's some reason that you need to do this in some cases, you might instead want to change the f parameter to take a type T instead. In this case I suspect you're doing it to lazily evaluate the function so that you don't have to evaluate if the result is already cached. That would probably be a valid reason, assuming you're not optimizing for performance prematurely.
You aren't creating a delegate. You are actually evaluating the method before calling GetObject. Easily fixed:
var foundItems = GetObject<List<string>>(key,
name => GetCultures<List<string>>(name));
Note also that it isn't obvious what you want to do with sitename in this scenario; you might instead mean this:
name => GetCultures<List<string>>(sitename));
Here's a complete example
public class TestDelegate
{
//You don't need generic here if you always return a list of string
public List<string> GetCulture(string s)
{
return new List<string> { s };
}
public T GetObject<T>(string key, Func<string, T> fn)
{
T foundItems = fn(key);
return foundItems;
}
public void Test()
{
List<string> test = GetObject("abc", x => GetCulture(x));
}
}
If you look at the method Test() and GetObject(), you can note 3 interesting things :
You don't have to specify the generic type on GetObject() because the compiler infer it from GetCulture()
The x parameter serves as an input to your delegate function, that way the method
GetObject can use the "key" and pass it to the delegate function.
I replace your delegate function by "Func" with a string input and a List output.

Returning a method from a C# method

I found this post that explains how to pass methods as parameters in C#.
What I need to know is how to return a method as the result of another method invocation.
method = DoSomething()
result = method()
you need to use either Action<T> or Func<T>
Like this:
private Action<string> Returns(string user)
{
return () =>
{
Console.WriteLine("Hey {0}", user);
};
}
or this:
private Func<bool> TestsIsThirty(int value)
{
return () => value == 30;
}
Most probably you want your return type to be a Delegate.
Check out the Action and Func delegates.
var method =()=> DoSomething();
result = method();

Categories