C# - Generic method with linq parameter - c#

I'm thinking of creating something like this:
Class.Method<OtherClass>(x => new Dictionary<string, string> { { nameof(x.Property), "Hello World!" } });
I'd like the Method to be void, but somehow I can't get this done. I understand that this signature is
public static void Method<T>(Func<T, Dictionary<string, string>> func)
but I don't want to use the dictionary az a TResult. All I want is to have a dictionary as an input and fill the keys from the T type. Is this possible somehow?

From what I can gather, you're trying to provide a function that populates keys for an existing dictionary. If that's the case, you could do something like this:
public static void Method<T>(Action<T, IDictionary<string, string>> mergeAction);
This can be called like this:
MyClass.Method<OtherClass>((input, dict) => { dict[nameof(input.Property)] = "hello world"; });

A Func<T, TResult> where TResult should return void must be declared as an Action<T>

Related

c# explode tuple into dictionary entry [duplicate]

This question already has answers here:
In C# 7 is it possible to deconstruct tuples as method arguments
(6 answers)
Closed 1 year ago.
Hi I have a function that returns a tuple of 2 values and I want to put them into a one-line add as seen below:
Dictionary<string, string> test = new Dictionary<string, string>();
test.Add(intoDict());
private (string, string) intoDict()
{
return ("Key","Value");
}
I need this to be a one-line operation.
If, for whatever reason it absolutely has to be a oneliner, you can create an extension method to handle the tuple value:
public static class Extension
{
public static void Add<TKey, TValue>(this IDictionary<TKey, TValue> dic, ValueTuple<TKey, TValue> tuple)
{
dic[tuple.Item1] = tuple.Item2;
}
}
which can then be called like this:
static (string, string) intoDict()
{
return ("Key", "Value");
}
static void Main(string[] args)
{
Dictionary<string, string> dic = new Dictionary<string, string>();
dic.Add(intoDict()); //added here
return;
}
You need to specify the key and value separately like below in Add method as it expects two parmeters, first key and second value :
var tupleResult = intoDict();
test.Add(tupleResult.Item1, tupleResult.Item2);
Consider using an extension method.
public static class DictionaryExtensions
{
public static void Add<T, U>(this IDictionary<T, U> Dictionary, (T, U) tuple)
{
Dictionary.TryAdd(tuple.Item1, tuple.Item2);
}
}
This extension method provides an .Add() to any IDictionary.
To use this simply do:
(string,string) myTuple = ( "Key", "Value");
dictionary.Add(myTuple);

Dictionary of functions with returning value C#

I'm having trouble creating dictionary of functions. The issue I'm running against is how to return value from called method.
I tried something like this but it's not working since I get error about returning value from anonymous function. I don't know how to properly invoke lambda since the examples I've seen have no arguments, while I have both input parameters and return value.
private static Dictionary<string, Action<String, String>> dictionary= new Dictionary<string, Action<String, String>>()
{
{"key",
(arg1, arg2) => {
Class instance= new Class();
return instance.MyFunction(arg1, arg2);)
}
}
And I want to call it as
dictionary["key"]("abc", "123");
I know making MyFunction static would be simpler but Class is implementing an interface and I'm working on C# 7.3
You need to use Func , not Action, since Action cannot return a value. The last Type argument to Func is the return type.
private static Dictionary<string, Func<String, String, String>> dictionary =
new Dictionary<string, Func<String, String, String>>()
{
{
"key",
(arg1, arg2) =>
{
Class instance = new Class();
return instance.MyFunction(arg1, arg2);
}
}
};
More information here: https://learn.microsoft.com/en-us/dotnet/api/system.func-2?view=netcore-3.1
You should use Func delegate instead of Action, since it'll return a value (unlike Action) of type specified by last type argument. Assuming that MyFunction returns string, you can declare it like
private static Dictionary<string, Func<string, string,string>> dictionary =
new Dictionary<string, Func<string, string, string>>
{
{
"key",
(arg1, arg2) =>
{
var instance = new Class();
return instance.MyFunction(arg1, arg2);
}
}
};
And invoke like
var result = dictionary["key"]("abc", "123");
You also should fix a typo with an extra bracket in your code.

Dynamic Function Mapping

I would like to define the following two functions:
void Map<T>(Func<T, string> mapper);
T Call<T>(string value);
Map needs to store the function that turns a string into a result of type T so that when the "Call" function is called with a type T and a string the appropriate function can be looked up and called.
I was thinking that map could store the function in a dictionary of type Dictionary<Type, Func<object, string>> and then Call could do the casting to the appropriate type but I'm unable to get that to work. Does anyone know how to achieve this?
The first type argument of Func is the input, the second the output: Func<in T, out TResult> -- so you need Func<string, T>.
(The MSDN reference here uses Func<string, string> a fair bit which is annoying.)
Also, the dictionary can't use the type argument T as that's different for each element in the dictionary. Rather, use the superclass of Func<T, TResult> which is Delegate.
This should work:
Dictionary<Type, Delegate> dictionary = new Dictionary<Type, Delegate>();
public void Map<T>(Func<string, T> mapper)
{
dictionary[typeof(T)] = mapper;
}
public T Call<T>(string value)
{
var func = dictionary[typeof(T)] as Func<string, T>;
return func.Invoke(value);
}
You can try and do something like this (there should be a better way, but I can't see it right now):
Dictinary<Type, object> _funcDict = ...;
void Map<T>(Func<T, string>mapper)
{
_funcDict[typeof(T)] = mapper;
}
T Call<T>(string value)
{
var func = (Func<T, string>)_funcDict[typeof(T)]
return func(value);
}
What I don't like, is having an object value type in the dictionary, but I'm not sure how you can avoid it.

C# Pattern to cache actions accepting generic parameters

I want to create a list of actions to perform on a drawing object. Here's what the non-generic code would look like:
private Dictionary<String, Action<Drawing, String>> actions = new Dictionary<String, Action<Drawing, String>>();
private void LoadActions()
{
actions.Add("Height", (d, s) => d.Height = Double.Parse(s));
actions.Add("Width", (d, s) => d.Width = Double.Parse(s));
}
private void ProcessDrawing(Drawing drawing, String prop, String value)
{
actions[prop](drawing, value);
}
The problem I have is that the Drawing class is a generic one (Drawing<T>) so I can't define actions like the following because T is not defined:
Dictionary<String, Action<Drawing<T>, String>> actions = new Dictionary<String, Action<Drawing<T>, String>>();
Without caching the code looks like this:
private void ProcessDrawing<T>(Drawing<T> drawing, String prop, String value)
{
var actions = new Dictionary<String, Action<Drawing<T>, String>>();
actions.Add("Height", (d, s) => d.Height = Double.Parse(s));
actions.Add("Width", (d, s) => d.Width = Double.Parse(s));
actions[prop](drawing, value);
}
So how can I cache a bunch of actions accepting a generic type of parameter?
Thanks,
The base class of all Actions is MulticastDelegate. You would have to define your dict as Dictionary<String,MulticastDelegate> and use appropriate castings after retrieving your actions from the dict.
EDIT:
Tests show that lambda expressions can obviously not be directly assigned to variables of type MulticastDelegate. This is because the type of the lambda expression parameters is inferred from the type of the variable (or method parameter) it is assigned to. Therefore assign it first to a variable with the right Action<> type. Then assign this to MulticastDelegate.
In the example, I show both versions (through a method parameter and through a variable):
public static void CallTestDelegate()
{
TestDelegate((d, s) => d.Height = Single.Parse(s));
}
public static void TestDelegate(Action<RectangleF, string> action)
{
Dictionary<String, MulticastDelegate> dict = new Dictionary<string, MulticastDelegate>();
dict.Add("a1", action);
Action<RectangleF, string> action2 = (d, s) => d.Width = Single.Parse(s);
dict.Add("a2", action2);
var a1 = (Action<RectangleF, string>)dict["a1"];
a1(new RectangleF(), "15");
}
One option is to make Drawing<T> derive from a non-generic interface IDrawing that has Height and Width properties, then change your actions to be of type Action<IDrawing,String>.
Another option (less type-safe) is to make your actions of type Action<dynamic,String>.
T is just a placeholder, make an abstract class or interface representing objects that you want

How do I store comparison functions in a Dictionary?

I would like to have my comparison functions accessible by using a key. This is what I have tried. I think my problem is how I'm declaring the type for the dictionary value.
internal static int CompareUsersByEmail(MembershipUser a, MembershipUser b)
{
// imagine null checking happening here.
return string.Compare(a.Email, b.Email, true);
}
public static void Sort(List<MembershipUser> list, string expression) {
// I can do this
list.Sort(CompareUsersByEmail);
// but not this
Dictionary<string, Func<MembershipUser, MembershipUser, int>> compareFns;
compareFns = new Dictionary<string, Func<MembershipUser, MembershipUser, int>>();
compareFns["Email"] = CompareUsersByEmail;
list.Sort(compareFns[expression]); // where expression would be "Email"
}
Is this possible?
Change your dictionary type to:
Dictionary<string, Comparison<MembershipUser>> compareFns;
I believe it will then work with no other changes. The method group conversion to Comparison<MembershipUser> will still work, and now you can call List<T>.Sort(Comparison<T>).

Categories