I have a class with a bunch of methods in it, the methods transfer variables elsewhere in my program when called. I want to use a dictionary as the middle man between the methods that transfer data and the methods that call them.
So here is my question. Say I make a dictionary, where the key is an int and I want the value to be the name of a method. I will assign a new value / method each time I add to the dictionary. Is there a value type I can put there that will let me do this?
Dictionary<int, ?> methodKey= new Dictionary<int, ?>();
I tried to find a list of types that dictionary will take but I couldn't find anything specific.
Thanks in advance
Use any delegate type as a type of value. For example:
Dictionary<int, Action>
So, you'll be able to write such things:
dictionary[0] = () => Console.WriteLine("0");
dictionary[1] = Foo;
dictionary[2] = a.Bar;
Specific delegate type depends on your needs - may be, you want for methods to have some input parameters or output/return values, but it should be most common type.
Will all the methods have the same signature? If so you can probably use one of the existing Action or Func delegate, (or you can create a delegate type with that signature), and use that as your second type parameter.
If not, you can use Delegate (or even object) and cast to the appropriate type when you invoke the delegates.
Related
I have a class that will require a varying number of Func delegates to be passed in the contructor. Each of these delegates will point to a different function, each with a different return type, and with a varying number of parameters (of type double). Each of these functions will then be called accordingly.
Question 1. Right now, to make things easier for those using this class, I am thinking about allowing the user to pass a List<object> of Func delegates. Is this possible, and if so am I able to determine the return type and number of params required for each Func in the method in which the List<object> is passed to (i.e. the constructor) ?
Question 2. If the above is not feasible, will I need to overload the constructor with every different combination of return types/number of params and route each Func accordingly -_- ... if not can someone point me in the right direction, I feel like i'm approaching this in the wrong way ...
note - coming from a python background, I would do something like this (i'm inexperienced in c#):
import inspect
def test(x): return x
inspect.getargspec(test)
returns: ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)
Many thanks
Question 1. Right now, to make things easier for those using this class, I am thinking about allowing the user to pass a List of Func delegates. Is this possible, and if so am I able to determine the return type and number of params required for each Func in the method in which the List is passed to (i.e. the constructor) ?
Not really. You could allow a List<Delegate> (or some other collection with an element type of Delegate), but nothing Func-specific, for two reasons:
Func is effectively a family of types, with different number of generic type parameters. These types are entirely separate as far as the CLR is concerned; Func<TResult> and Func<T, TResult> are as different as Action<T> and EventHandler.
Even if you were only dealing with several values of the same generic type of delegate, the fact that they could have different type arguments means they're different types to the CLR; there's no way of saying List<Func<>> for "a list of functions with potentially varying type arguments". Again, the CLR treats them as separate types - although this time at least one with a common generic type definition.
Question 2. If the above is not feasible, will I need to overload the constructor with every different combination of return types/number of params and route each Func accordingly
Well, there are several options:
Make all the parameters optional, giving each of them a default value of null, then use named arguments when calling the constructor:
var foo = new Foo(clickHandler: () => ...,
keyHandler: key => ...);
Create a builder, so that the various functions can be set as properties - this works very well with the object initializer syntax:
var foo = new Foo.Builder {
ClickHandler = () => ...,
KeyHandler = () => ...
}.Build();
Both of the latter solutions depends on you really having a specific named purpose, of course.
It would help if you could be clearer about what you're trying to achieve - as dtb says, polymorphism may be a better fit here. You could create an abstract class with no-op implementations of virtual methods, and implementations could choose which ones to override.
I'm working on a binary search algorithm, which has the following parameters:
Now when I pass these arguments:
It says that type int cannot be used as a parameter F (I was under the impression that the generic types are not concerned with types that are being passed) and that there are no 'boxing' conversion from int to IComparable.
What I was trying to do: Basically, I wanted this method to accept search key's which can be of various numeric types (ints, doubles etc.) and so in the generic method I tried to declare two types.
About this code:
The func delegate represents an object's property i.e. car.Name (string), car.Wheels(int) which are of different types. I Sort of want the key data type somehow be inferred based on the propertyFields type that's being passed, but that seems way too complicated, so I tried making it so that the F Key accepts various types and just make sure that I'm passing the correct types to it.
I don't know if this all sounds confusing, but if you have questions about any of my code, feel free to ask.
Edit: The error occurs when I call the BinarySearch Method.
Edit 2: for the propertyField i pass this as an argument: c => c.Longitude (or any other object property).
Either your 2nd constraint needs to be where F : IComparable<F> or you should not have a F at all and you should be taking in a T Key instead of a F Key
So I have:
ConcurrentDictionary<string, int> dict;
I want to pass a reference to one of its elements, suppose dict["x"] to a method, and allow that method to change/set that element. Is it possible to do exactly that, or do I have to pass the dictionary itself? Also, is it possible to do so even if the element does not exist as a key in the dictionary? Or does it already has to be a valid key contained in the dictionary?
Yes, by using a delegate. This delegate can be called from within the changing function. The delegate will then change or set the key/value inside the dictionary.
void DoChangeMyElement<T>(Action<T> changeIt)
{
changeIt(123);
}
You can call this method with:
ConcurrentDictionary<string, int> dict = new ...;
DoChangeMyElement(value => dict["X"] = value);
I want to pass a reference to one of its elements, suppose dict["x"] to a method, and allow that method to change/set that element. Is it possible to do exactly that, or I have to pass the dictionary itself ?
Just pass the dictionary, as Sam I am said it is a reference type anyway.
Also, is it possible to do so even if the element does not exist as a key in the dictionary ?
No that's not possible, you'd have to add to it, then send it to the function.
You'd have to pass the whole dictionary and key, and let the method do what it needs to. The basic reason for this is that you can only pass fields and local variables by reference, not properties (including indexer properties).
If you were really desperate to do so, you could use reflection and/or delegates to get what you want done, but it's not the best way to do it.
There's no harm in passing the whole Dictionary. It itself is a reference type after all, and passing the Dictionary would be better form than passing by reference.
but I suppose you could encapsulate you int and pass it like that
public class IntContainer
{
int value;
}
I have a class that will require a varying number of Func delegates to be passed in the contructor. Each of these delegates will point to a different function, each with a different return type, and with a varying number of parameters (of type double). Each of these functions will then be called accordingly.
Question 1. Right now, to make things easier for those using this class, I am thinking about allowing the user to pass a List<object> of Func delegates. Is this possible, and if so am I able to determine the return type and number of params required for each Func in the method in which the List<object> is passed to (i.e. the constructor) ?
Question 2. If the above is not feasible, will I need to overload the constructor with every different combination of return types/number of params and route each Func accordingly -_- ... if not can someone point me in the right direction, I feel like i'm approaching this in the wrong way ...
note - coming from a python background, I would do something like this (i'm inexperienced in c#):
import inspect
def test(x): return x
inspect.getargspec(test)
returns: ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)
Many thanks
Question 1. Right now, to make things easier for those using this class, I am thinking about allowing the user to pass a List of Func delegates. Is this possible, and if so am I able to determine the return type and number of params required for each Func in the method in which the List is passed to (i.e. the constructor) ?
Not really. You could allow a List<Delegate> (or some other collection with an element type of Delegate), but nothing Func-specific, for two reasons:
Func is effectively a family of types, with different number of generic type parameters. These types are entirely separate as far as the CLR is concerned; Func<TResult> and Func<T, TResult> are as different as Action<T> and EventHandler.
Even if you were only dealing with several values of the same generic type of delegate, the fact that they could have different type arguments means they're different types to the CLR; there's no way of saying List<Func<>> for "a list of functions with potentially varying type arguments". Again, the CLR treats them as separate types - although this time at least one with a common generic type definition.
Question 2. If the above is not feasible, will I need to overload the constructor with every different combination of return types/number of params and route each Func accordingly
Well, there are several options:
Make all the parameters optional, giving each of them a default value of null, then use named arguments when calling the constructor:
var foo = new Foo(clickHandler: () => ...,
keyHandler: key => ...);
Create a builder, so that the various functions can be set as properties - this works very well with the object initializer syntax:
var foo = new Foo.Builder {
ClickHandler = () => ...,
KeyHandler = () => ...
}.Build();
Both of the latter solutions depends on you really having a specific named purpose, of course.
It would help if you could be clearer about what you're trying to achieve - as dtb says, polymorphism may be a better fit here. You could create an abstract class with no-op implementations of virtual methods, and implementations could choose which ones to override.
I want to pass a method around and store it. Let's say the method takes one int and returns void. I'd wrap it in Action< int >.
Now, is there a way to invoke that method but not on the object it originated from but a different instance of the same class?
It's kind of hard to be more specific than that but please ask if anything is confusing and I'll try again.
Now, is there a way to invoke that method but not on the object it originated from but a different instance of the same class?
EDIT: Okay, ignore my first attempt. I thought you were talking about a different class.
It sounds like you should actually be wrapping the method in an Action<object, int> (or a more strongly typed version).
Alternatively, you could create a new delegate using:
Action<int> newAction = (Action<int>) Delegate.CreateDelegate(typeof(Action<int>),
newTarget,
oldAction.Method);
You can use the Type.GetMethod overload which takes parameter types. This allows you to get the exact method with the specified parametere types.