C # multiple send options?

I have the following classes:

class Asset { } class House:Asset { } 

consider these extraneous static functions:

 static void Foo (Asset a) { } static void Foo (House h) { } 

If I write:

 House h = new House (...); Foo(h); 

it will call Foo(House) (compile time binding)

if i write:

 Asset a = new House (...); Foo(a); 

it will call Foo(Asset) (compile time binding)

goal

: access the runtime type method:

I have 2 options:

1) using dynamics as follows:

  Asset a = new House (...); Foo ((dynamic)a); // NOW it will call Foo(House) 

2) move functions from static to override using the polymorphism mechanism .

question :

is there any other way to do this (without moving functions to the polymorphism mechanism || dynamic )?

+6
source share
3 answers
goal

: access the runtime type method

What is the dynamic keyword for this? This is actually a pretty clean and quick way to do multiple submissions.

Your Final Options Multiple Dispatch -

  • dynamic
  • Virtual Double Dispatch Methods
  • Some hashed collections of anonymous function rules
  • if (x is House) ... else if(x is Asset)...
  • The reflection is really slow and ugly

question: is there any other way to do this (without moving functions to the polymorphism mechanism || dynamic)?

So, there are ways to do this in order to do a lot of work on your part, when you can just use dynamic , which is fast, less error prone and really clean syntax .

+9
source

I think this is what happens under the hood of Foo((dynamic)a) :

 Asset a = new House(); Type t = typeof(MainClass); t.InvokeMember("Foo", System.Reflection.BindingFlags.InvokeMethod, null, t, new object[] { a }); 

That will solve Foo(House h)


A quick trip to the monodis.exe file without using reflection (for example, InvokeMember), that is, the dynamic keyword Asset a = new House(); Foo((dynamic)a) is used instead Asset a = new House(); Foo((dynamic)a) Asset a = new House(); Foo((dynamic)a) , this is IL:

 IL_0025: ldstr "Foo" IL_002a: ldnull IL_002b: ldtoken MainClass IL_0030: call class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) 

To a large extent, what your hunch will tell you, “Foo” is a dead sale, that dynamics is an activity.

Now it is sans dynamic, i.e. Asset a = new House(); Foo(a) Asset a = new House(); Foo(a) :

 IL_0010: ldloc.0 IL_0011: call void class MainClass::Foo(class Asset) 

The burnt instruction is largely resolved; it will not change; it always allows Foo(Asset);

Here is the complete code that you can use to analyze dynamic behavior (via monodis.exe or ildasm.exe):

 using System; public class MainClass { public static void Main() { Console.WriteLine("Hei"); Asset a = new House(); Foo(a); Foo((dynamic)a); object x = 7; Foo((dynamic)x); } public static void Foo(House h) { Console.WriteLine("House"); } public static void Foo(Asset a) { Console.WriteLine("Asset"); } public static void Foo(int i) { Console.WriteLine("int"); } } public class Asset { } public class House : Asset { } 

Conclusion:

 Hei Asset House int 

This will cause the Foo int to overload, i.e. Foo(int i) :

 object x = 7; t.InvokeMember("Foo", System.Reflection.BindingFlags.InvokeMethod, null, t, new object[] { x } ); 

It is too:

 t.InvokeMember("Foo", System.Reflection.BindingFlags.InvokeMethod, null, t, new object[] { 8 } ); 

So, to your question, what other option can you use, you can use a method that takes an unexplored object:

 public static void FooDynamic(object o) { Type t = typeof(MainClass); t.InvokeMember("Foo", System.Reflection.BindingFlags.InvokeMethod, null, t, new object[] { o } ); } 

To call:

 Asset a = new House(); FooDynamic(a); // will select Foo House overload int i = 7; FooDynamic(i); // will select Foo int overload 

You can also use this API for the code above: public static void Foo(object o) , then you will need to call Foo as follows:

 Asset a = new House(); Foo((object)a); // will resolve to House 

Given that C # 4 already has the dynamic capability, it would be difficult for me to use reflection if the developer is still not using C # 3. Thus, instead use the dynamic approach :-)


UPDATE

Why is it slow dynamic (at least on Mono), when I run this code, it takes about 2 seconds before the letter “B” appears. Dynamic delay is reproducible, even I change the order of the dynamic and reflection code. The delay of reflection is imperceptible, it is faster than dynamic.

 using System; public class MainClass { public static void Main() { // there a delay on initial dynamic call, about two seconds Test (); Console.ReadLine (); // dynamic speed is instant on subsequent calls, // as clarified by Eric Lippert, the delegate is cached, // hence the elimination of delay on subsequent dynamic calls Test (); } public static void Test() { Asset a = new House(); Console.WriteLine("A"); Foo((dynamic)a); // there is a considerable delay here, the "B" string appears after two seconds Console.WriteLine ("B"); Type t = typeof(MainClass); t.InvokeMember("Foo", System.Reflection.BindingFlags.InvokeMethod, null, t, new object[] { a } ); Console.WriteLine("C"); } public static void Foo(House h) { Console.WriteLine("House"); } public static void Foo(Asset a) { Console.WriteLine("Asset"); } public static void Foo(int i) { Console.WriteLine("int"); } } public class Asset { } public class House : Asset { } 
+1
source

If you want a static entry point, but you also need polymorphic behavior, then the simplest mix would be to use a singleton pattern. It will give you a static entry point, and the returned object will have polymorphic methods.

I also suggest ignoring everyone who says singleton is horrible, bad. Prima Donna singleton sermon is a mid-level shibboleth of developers. Singleton is just a tool, and if it suits your needs, then use it.

+1
source

Source: https://habr.com/ru/post/914206/


All Articles