In C++ we have the std::function type which can be used to wrap lambdas, functions and even custom classes. Here is an example of a custom class wrapped in std::function:
#include <functional>
struct A {
void operator()() {
}
};
std::function<void()> a = A();
I though the same was possible with delegates in C# but, I can not get it to work:
class Program
{
delegate void Foo();
class Bar
{
public void Invoke()
{
}
}
static void Main()
{
new Foo(new Bar()); // CS0149: Method name expected
}
}
I am convinced that this has to be possible somehow, because the delegate operator internally creates a new class that inherits from System.Delegate which suggests that I can create my own type to do the same somehow.
Simple answer is 'no' because C# doesn't have an operator() in the way C++ does.
However, a lambda can be used to store not just a function, but a function on a specific object.
class Program
{
delegate void Foo();
class Bar
{
public void Invoke()
{
}
}
static void Main()
{
var f = new Foo(new Bar().Invoke);
}
}
The difference is simply that in C# you have to specify the method name, rather than there being a default.
Also worth noting that similarly to C++, C# has generics to help this, so we can cut out the Foo declaration altogether:
var f = new Action(new Bar().Invoke);
Related
Is there a way I could use reflection to hook one function to another without using delegates?
class A
{
void Foo()
{
}
}
class B
{
void Main()
{
A a = new A();
a.GetType().GetMethod("Foo").AddHook(a, Func); //I want something like this
a.Foo();
//Func gets called
}
void Func()
{
}
}
Is there a way to call Func after Foo was called without using events, delegates or just calling Func from inside Foo?
I need this so my game's UI controller can get updated.
The way I see most people dealing with this is by adding a bunch of events to A and subscribing B to those. Like this
class A
{
public delegate void UICallback();
public event UICallback onFoo;
void Foo()
{
onFoo.Invoke();
}
}
class B
{
void Main()
{
A a = new A();
a.onFoo += Func;
a.Foo();
}
void Func()
{
}
}
The problem I find with this approach is that I'd need to add a bunch of events like these (probably more than 5 or even 10) to many classes and then remember to invoke those at the end of a function to update UI (invoke onBattleStarted at the end of StartBattle(), for example). This, in addition to increasing the size of my classes with big blocks of event declarations making it ugly to read, makes it a harder maintain.
EDIT I think no one really understands what I'm looking for... I'd like a way to hook Func to Foo without making any changes to Foo, i.e. without Foo knowing this callback exists. Using an action won't help since I'd need specify on Foo's parameters that it should call Func
Thank you for your help!
You Can call Action at the end of Func().
Class A
{
void Foo()
{
}
}
Class B
{
void Main()
{
A a = new A();
Func( () => {a.Foo();});
}
void Func(Action onFinish)
{
//Enter your code here
onFinish();
}
There is the method chaining pattern if that can solve your problem:
namespace Assets
{
public class Example
{
public Example GrabSomeFoodInTheFridge()
{
// some work
return this;
}
public Example WatchTv()
{
// some work
return this;
}
public Example EatFood()
{
// some work
return this;
}
}
public class Demo
{
public Demo()
{
var example = new Example();
var instance = example
.GrabSomeFoodInTheFridge()
.EatFood()
.WatchTv();
}
}
}
It does not use reflection at all, additionally you could leverage interfaces and extension methods.
Internally, the compiler should be translating lambda expressions to methods. In that case, would these methods be private or public (or something else) and is it possible to change that?
It depends. With the current version of Visual Studio, the methods that implement lambdas are never public, but they're not always private. A simple program to test some versions of lambdas:
public class Program
{
public static void Main()
{
var program = new Program();
Try("A", program.A);
Try("B", program.B);
Try("C", program.C);
Console.ReadKey();
}
private static void Try(string name, Func<Action> generator)
{
var mi = generator().Method;
Console.WriteLine($"{name}: DeclaringType={mi.DeclaringType}, Attributes={mi.Attributes}");
}
private Action A() => () => { };
private Action B() => () => { ToString(); };
private Action C()
{
var c = 1;
return () => c.ToString();
}
}
prints
A: DeclaringType=Scratch.Program+<>c, Attributes=PrivateScope, Assembly, HideBySig
B: DeclaringType=Scratch.Program, Attributes=PrivateScope, Private, HideBySig
C: DeclaringType=Scratch.Program+<>c__DisplayClass4_0, Attributes=PrivateScope, Assembly, HideBySig
A's lambda doesn't have any captures. It's created as an internal method of an empty closure class.
B's lambda captures this. It's created as a private method of the containing class.
C's lambda captures c. It's created as an internal method of a non-empty closure class.
All of this is undocumented and has changed in the past, so it would be good to avoid relying on it. What matters is that when you call the anonymous method, it behaves as specified. If you need anything more than that, you shouldn't be using anonymous methods. Depending on what you're after, you might either still be able to use lambdas, but with expression trees, or you might need to create regular named methods instead.
Internally, the compiler should be translating lambda expressions to methods.
I assume by "lambda" you mean a lambda converted to a delegate type. Lambdas converted to expression tree types are certainly not generated as methods.
The compiler does in fact turn such lambdas into methods, yes. There is no requirement that it does so, but doing so is convenient.
In that case, would these methods be private or public (or something else) and is it possible to change that?
The question is somewhat incoherent. Suppose I told you that a lambda was a public method. It has no name accessible from C#; how would you take advantage of its public-ness? Accessibility modifiers apply to members with names. The very notion of accessibility domain gives the domain of a name during name resolution.
In practice of course the compiler has to generate some accessibility bits for the metadata of the uncallable-by-you method. Methods generated on closure classes are internal, as that is the most convenient way to make usage of them verifiable. Methods generated without closures can be private.
Again, none of this is required, and all of it is implementation detail subject to change. You should not be attempting to take advantage of the code generation details of the compiler.
From the CLR via C# book by Jeffrey Richter
The compiler automatically defines a new private method in the class
... The compiler creates the name of the method for you automatically
... anonymous methods generated by the compiler always end up
being private, and the method is either static or nonstatic depending
on whether the method accesses any instance members
So the method is declared as private or internal.
For example the code
class AClass {
public void SomeMethod() {
Action lambda = () => Console.WriteLine("Hello World");
lambda();
}
}
will produce IL declaration as
.field private static class [mscorlib]System.Action 'CS$<>9__CachedAnonymousMethodDelegate1'
As you can see it is private static field.
However notice that lambda expression can be optimized, if you change example to
class AClass
{
string a = "Hello World";
public void SomeMethod()
{
Action lambda = () => Console.WriteLine(a);
lambda();
}
}
compiler will optimize it and there would be no lambda declaration at all
IL_0001: ldstr "Hello World"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
As #hvd mentioned there's a difference between a lambda expression uses parameters from its surrounding environment (closure case) or not. See: Why do some C# lambda expressions compile to static methods?
So the question only makes sense for the non-closure case when the lambda expression can be converted into a delegate wrapper without having any outside dependencies.
You can pass that generated class (which basically wraps a delegate) around and it will always refer to the generated delegate in the defining assembly. So you can invoke it from anywhere if the assembly is referenced.
Just verified that passing and executing an Action defined in another assembly works although the Action.Method itself is marked internal.
// Main, first assembly
namespace ConsoleApplication1
{
public class B : IB
{
Action _action;
public void AddAction(Action act)
{
_action = act;
}
public void Invoke()
{
Console.WriteLine(_action.Target);
Console.WriteLine("Is public: {0}", _action.Method.IsPublic);
_action();
}
}
class Program
{
static void Main(string[] args)
{
var a = new A();
var b = new B();
a.AddActionTo(b);
b.Invoke();
Console.ReadKey();
}
}
}
In other assembly:
namespace OtherAssembly
{
public interface IB
{
void AddAction(Action act);
}
public class A
{
public void AddActionTo(IB b)
{
Action act = () => { };
b.AddAction(act);
}
}
}
Is it possible to exchange implementations of methods in C#, like method swizzling in Objective-C?
So I could replace an existing implementation (from an outside source, via a dll for example) at runtime with my own (or add another onto it).
I have searched for this, but have found nothing of value.
You could use delegates to have your code point to whatever method you wish to execute at run time.
public delegate void SampleDelegate(string input);
The above is a function pointer to any method which yields void and takes a string as input. You can assign any method to it which has that signature. This can also be done at run time.
A simple tutorial can be also found on MSDN.
EDIT, as per your comment:
public delegate void SampleDelegate(string input);
...
//Method 1
public void InputStringToDB(string input)
{
//Input the string to DB
}
...
//Method 2
public void UploadStringToWeb(string input)
{
//Upload the string to the web.
}
...
//Delegate caller
public void DoSomething(string param1, string param2, SampleDelegate uploadFunction)
{
...
uploadFunction("some string");
}
...
//Method selection: (assumes that this is in the same class as Method1 and Method2.
if(inputToDb)
DoSomething("param1", "param2", this.InputStringToDB);
else
DoSomething("param1", "param2", this.UploadStringToWeb);
You can also use Lambda Expressions: DoSomething("param1", "param2", (str) => {// what ever you need to do here });
Another alternative would be to use the Strategy Design Pattern. In this case, you declare interfaces and use them to denote the behavior provided.
public interface IPrintable
{
public void Print();
}
public class PrintToConsole : IPrintable
{
public void Print()
{
//Print to console
}
}
public class PrintToPrinter : IPrintable
{
public void Print()
{
//Print to printer
}
}
public void DoSomething(IPrintable printer)
{
...
printer.Print();
}
...
if(printToConsole)
DoSomething(new PrintToConsole());
else
DoSomething(new PrintToPrinter());
The second approach is slightly more rigid than the first, but I think it is also another way to go around achieving what you want.
The only way to "replace methods" is to use delegates.
If your code looks like this:
public void Foo()
{
Bar();
}
public void Bar()
{
}
Then you cannot get Foo to call any other method than Bar. The method dispatch table you refer to in Objective-C is not mutable in .NET.
To be able to specify which method Foo should call above you need to use a delegate:
public void Foo(Action whichMethod)
{
whichMethod();
}
And you could call it like this:
Foo(Bar);
Foo(Baz);
But the method has to be built to allow this kind of runtime replacement.
While this isn't the best path to object-oriented programming in a strongly-typed language, it's worth to mention that since .NET 4.0, C# has included the Dynamic Language Runtime (DLR) which allows dynamic programming. One of most curious dynamic objects is ExpandoObject: a fully runtime-expandable object:
dynamic expando = new ExpandoObject();
expando.DoStuff = new Func<string>(() => "hello world");
// Now you can swap DoStuff with other method setting another delegate:
expando.DoStuff = new Func<string, string>(text => text + "!");
BTW, as I said above, I've shared this approach here just for learning purposes. It might be useful in some edge cases, but as C# is a compiled and strongly-typed language, you should avoid this approach in 99.99% of cases.
void Test(Action method) {
if ( method != null ) method.invoke();
}
you can call this
Test( () => { Console.WriteLine("hello world"); } )
change def and call again
Test( () => { MessageBox.Show("Hi"); } )
I have trouble understanding lambdas, delegates and so on, I hope with someone giving me a solution to my problem I am able to understand those better. Basically it is possible to create (or change) the body of a method when an object of the class is initialized, no?
Kinda like this:
Let's say I have 1 classes: Class A, which looks like this:
public class ClassA{
int i;
public ClassA(int number)
{
i = number;
}
public void Foo(){}
}
For demonstration purposes very minimalistic, now I also have somewhere else the static main, and what I want to do there is following: Creating multiple objects of ClassA and make it so that when I call ClassA.Foo I get different results I can determine myself, how is it supposed to look Syntax wise?
static void Main(string[] args)
{
ClassA FooBlue = New ClassA(1){
public void Foo()
{
System.Console.WriteLine("I am a Fooranger Blue!");
};
ClassA FooPink = New ClassA(2){
public void Foo()
{
System.Console.WriteLine("My color is the manliest!");
};
...
So now when I do this:
...
FooBlue.Foo();
FooPink.Foo();
System.Console.ReadLine();
}
I get following output on the console:
"I am a Fooranger Blue!"
"My color is the manliest!"
I just mention again that this is an example and by no means anything out of praxis but for the purpose of me understanding that stuff it would be great if someone can provide an answer that gives the desired solution, including the useless integer i.
To accomplish the goal of "providing the implementation of a method when constructing the type" you can indeed use delegates. Simply accept a delegate when constructing the object and invoke it when you want it to be executed:
public class ClassA
{
private Action action;
public ClassA(Action action)
{
this.action = action;
}
public void Foo()
{
action();
}
}
The syntax for a lambda is different than the syntax for creating a named method from a class' definition:
var fooBlue = new ClassA(() => Console.WriteLine("I am a Fooranger Blue!"));
Hey i want to implement delegate in c++ i know how to do in c# i posting my code but don't know how i convert this to c++
public class Events {
public delegate void Action();
public Action OnPrintTheText = delegate{};
}
public class ABC {
private Event evt;
public ABC() {
evt = new Event();
}
public void printText() {
evt.OnPrintTheText();
}
public Event getEventHandler() {
return evt;
}
}
public class Drived {
private ABC abc;
public Drived() {
abc = new ABC();
abc.getEventHandle().OnPrintTheText += OnPrint;
}
~Drived() {
abc.getEventHandle().OnPrintTheText -= OnPrint;
}
public void OnPrint() {
Debug.Log("ABC");
}
}
now whenever i call printText it will automatically call the OnPrint() of Drived class so is there anyway to implement this to c++?
C# does a lot of management behind the scenes. Broadly, a delegate in C# is a container of function references.
In C++, you can create a similar delegate by using a functor template that wraps an object instance and a member function for class member functions, and also one that just wraps a function (for non members). Then you can use a standard container to maintain the list/array/map/etc of the instances of the functors, and this will provide you with the functionality of the C# delegate and also allow adding and removing 'actions' (C#: += and -=).
Please see my answer here on how you can create such a templated functor for class members. The non-member case is simpler since it does not wrap an object instance.
Take a look at function pointers:
http://www.newty.de/fpt/index.html
A function pointer is a pointer that points to a specific function, basically what a delegate is.
Look at this:
What is the difference between delegate in c# and function pointer in c++?