I made a method to loop and clear all textbox controls in my form.
Controls.OfType<TextBox>()
.ToList()
.ForEach(tb => tb.Clear());
This works just fine, but I figured that since the first argument passed to any instance method is always a reference to the instance that I should be able to write it like this
Controls.OfType<TextBox>()
.ToList()
.ForEach(TextBox.Clear);
Unfortunately that doesn't actually work, and I don't quite understand why..
It would work if TextBox.Clear was a static method with a TextBox parameter; but instead, it's an instance method with no parameters, so the compiler can't automatically transform it to an Action<TextBox>.
Note that the CLR does support open-instance delegates (you can create one with the Delegate.CreateDelegate method), but the C# language doesn't support it.
Here's how to create an open-instance delegate that will invoke TextBox.Clear on its argument:
var action = (Action<TextBox>)Delegate.CreateDelegate(
typeof(Action<TextBox>),
null,
typeof(TextBox).GetMethod("Clear"));
The this parameter is implicit, not explicit. Foreach is expecting a method with an explicit parameter, not an implicit one.
As for why the C# language team didn't implement this feature, you'll have to ask them. They of course could have designed the language to support this, if they wanted to. There's no real point in us speculating as to why they didn't.
Related
I am new to C#. I have read that the use of the keyword dynamic is somewhat controversial, and that other methods may be preferred depending on the use case. I want to make sure that my use of dynamic is appropriate for the language and the case. I'm working with this code:
public void myMethod(Action<T> myFunc) {
dynamic arg = "example"; // a string
myFunc(arg);
}
I don't know what the type T will be until runtime, and so I thought that dynamic would be useful. In the event that T is a string, I want to invoke myFunc with that argument. Is using dynamic the best way to do this in C#?
edit: To give more context, if T is string, then I want to pass arg to myFunc. If I don't use dynamic, I get an error that "cannot convert from 'string' to 'T'". Using dynamic solves this problem, I'm just not sure if it's the best way to solve it.
No. That is not an appropriate usage. You code will fail at runtime if T is anything other than string. That is the thing with dynamic, it turns of compiler checks, it does not mean your code will run, only that compiler errors turn into runtime errors. Dynamic is intended for interoperability with dynamic languages, or COM, where you are forced to cast objects at runtime anyway, so dynamic just makes it easier, without loosing any actual safety.
If you want to give myFunc a string, declare it as Action<string>. If you want to create a new object and give it to myFunc, add a new() restriction, i.e.
public void myMethod(Action<T> myFunc) where T : new(){
myFunc(new T());
}
If you don't know how to construct T, let the caller give it to you:
public void myMethod(Action<T> myFunc, T value) {
myFunc(value);
}
You can also use Func<T> to give your method a delegate that constructs values on demand.
Also Action<T> would be called a "generic delegate". Even if c++ templates and c# generics are used for a similar purpose, they work in a very different way. In effect c# generics is more restrictive, but also makes compiling much faster and easier since you do not have to generate code for each specialization until it is jitted.
For a test, I want to create a generic "helper" method which will take take two arguments, the first argument is a function (or a reference to the function) and the 2nd argument is a list of objects for that function that are to be called as its parameters.
The following does this perfectly:
CallMyFunctionWithParamsPlease(new Func<int, int>(MyMethod), new object[] {1});
public static int CallMyFunctionWithParamsPlease(Delegate func, params object[] args)
{
func.DynamicInvoke(args);
return 3;
}
The thing is, this doesn't look very nice when calling it and I wish to abstract it into another method to act as syntatic sugar.
Ideally I want it to be called like this:
CallMyFunctionWithParamsPlease(myMethod, new Object[] {1});
From what I can gather, there is no elegant solution to do this in C# since I cannot pass myMethod by itself as a reference anywhere, instead I must pass it by declaring a new Func along with the return type of the method. Since I'm not using this return type anywhere, I'm not sure why it's necessary to input this information. My limited understanding is that because C# is statically typed, the compiler must know everything and things like this just aren't possible.
Is this true or not? How would I create syntatic sugar to simply pass a method to another method which can be called there without needing to invoke "new Func"? I would have thought simply passing the function as a reference pointer would allow me to do this, but I'm having difficultly doing this too. I looked into delegates, using "unsafe" with pointers, and a few other options. None of them seem to make this possible, or if they do, they didn't explain it in a manner that I could understand.
I simply want to pass a method to another method, and invoke it with a variable list of object params with variable length whereby I don't need to specify this whilst invoking it. I'm not sure if I'm trying to force C# to do something it's not meant to do here, and instead I'd be better off using a dynamically typed language to do this. The problem is I really enjoy the intellisense that the static typing of C# offers, along with the performance improvements over a language like Python. I'd just like a way to syntactically abstract away the boilerplate with my own helper methods for things like this.
UPDATE: Thanks to the comments here it seems I can do this with a lambda expression nice and elegantly. The signature can be simply changed to public static long CallMyFunctionWithParamsPlease<T>(Func<T> func)
If deferred execution is what you want simply pass a Func<TReturnType> to your method (or class). The calling method doesn't need to know how many parameters are involved.
e.g. Assuming MyMethod has a signature int MyMethod(int arg):
CallMyFunctionWithParamsPlease(() => MyMethod(1));
public static int CallMyFunctionWithParamsPlease(Func<int> func)
{
return func();
}
If MyMethod takes two parameters, it's the same call:
CallMyFunctionWithParamsPlease(() => MyMethod(1, 2));
I would like to know how to pass a property to a method.
Currently, this is my method:
public static string Pick(this IFilePicker openFileService, Func<string> getCurrentFolder, Action<string> setCurrentFolder)
I use it to pick files (with a dialog). It automatically sets the current folder of the OpenFileDialog calling the getCurrentFolder Func. If the user correctly selects a file, then, the setCurrentFolder action is called.
I'm using it like this:
Pick(openFileService, () => Settings.Current.Folder, str => Settings.Current.Folder = str);
But it looks cumbersome to me. Why use 2 parameters instead 1? I could just pass the property.
But how?
I would like to call it like this:
Pick<Settings>(openFileService, x => x.Current.Folder);
Is that even possible?
NOTE Settings.Current is a Singleton. It's autogenerated.
Unfortunately there's no clean way of doing this. The code you've got is the simplest approach, I believe.
You could change the method to accept an Expression<Func<string>> instead, then examine the expression tree to get the property... but it would be a lot of effort, be less efficient, and give you less compile-time checking. You'd still need to pass () => Settings.Current.Folder - it would only remove the need for the final parameter.
To be specific, in your case you'd need to build an expression tree that still accessed the getter for Settings.Current, but then the setter for Folder. You'd then need to compile both expression trees.
It's all feasible, but it's a lot of fiddly work. Your current approach is clunky but simple. Unless you need to do this a huge amount, I'd just accept the clunkiness.
Assuming Settings.Current doesn't change, the other option would be to pass in the name of the property, so you'd call it with:
Pick(openFileService, Settings.Current, nameof(Settings.Folder));
That would still require reflection and would be somewhat error-prone, IMO.
A property is nothing but a package of two methods, a get- and a set-method. So by providing a property within a delegate, you reference either the one or the other. Thats why you can´t read and write the properties value within the delegate.
In order to read a property you surely need some method that returns a string and expects nothing (namely a Func<string>). When you want to set a property, you´ll need something that excepts a string. but doesn´t return anything (an Action<string>).
Furthermore, let´s see how the delegate could be defined:
Pick(string file, Delegate readAndWriteDelegate)
{
// what can you do with the delegate? You don´t know if you can provide a string or if it returns one
// do I have to use this?
readAndWriteDelegate(file);
// or this?
var result = readAndWriteDelegate();
// or even this?
var result = readAndWriteDelegate(file);
// in fact I could even use this
MyClass m = readAndWriteDelegate(3);
}
I just used the existing Delegate to show there´s no way to even declare your delegate and provide its type-safety.
Leaving asside that the code above won´t even compile as we´d have to call Invoke on the Delegate, you see it´s completely unclear what your delegate actually expects and what it returns. Even if we could determine it´s some kind of a stringdelegate, it´s unclear if the delegate should return a string or expect one or even do both and thus how we can call it.
Suggested just returning the path, but actually Pick() method needs to return the file as well as setting the path.
I'd add an overload or new method to the OpenFileService which will read/set the Path in the Settings.Current object, so the calls don't have to care where the 'current' path comes from. I'm assuming that 90+ % of the time you'll always read Settings.Current.Path and Write back to Settings.Current.Path so it's probably best to make the OpenFileService handle this, rather than every call to it?
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.
I recently noticed the following code which basically defines a class method
public Func<string, string> SampleMethod = inputParam =>
{
return inputParam.ToUpper();
};
which is the same as doing it in the old fashioned way
public string SampleMethod(string inputParam )
{
return inputParam.ToUpper();
}
My question - why would I prefer the first over the second? My eyes are maybe more trained to understand the second style quicker. I find it similar to the difference between SMS lingo and plain old english.
Those two things are fundamentally different. The former is a field of a delegate type while the latter is really a method. The tiniest difference I can think of is that you can modify the first one dynamically at runtime and assign another method reference to it while the second is fixed.
You shouldn't normally prefer the first over the second if your purpose is to write a simple method for a class in C#.
An example that makes the first extremely fragile:
var c = new SomeClass();
c.SampleMethod = inputParam => inputParam.ToLower();
c.DoSomeTaskThatReliesOnSampleMethodReturningAnUpperCaseString();
c.SampleMethod = null;
c.DoSomeTaskThatCallsSampleMethod(); // NullReferenceException
This style of programming is common in language like Javascript where an object is fundamentally a dynamic creature built upon a simple dictionary.
They are actually not the same at all. The second is a regular member method, that returns ToUpper on the input string.
The first, on the other hand, is a Func member variable, that happens to point to a delegate, that implements the same functionality. However, as this is a method pointer, you can substitute the delegate with any other delegate of the same type at runtime. I.e. you can completely redefine what it means to call this method.
One benefit of the second way is it's better from a unit testing perspective - you can test your class and know that the method will correctly return the uppercase string. With the first method, you can change the method at runtime, so unit testing is much harder.