C# : why can I not use dynamic param in an extension method? - c#

Why can I not use dynamic param in an extension method, as in the following code:
public static class Extension
{
public static void ExtMethod(this Program pg, object asdf) {
new Program();
}
}
public class Program
{
static void Main(string[] args)
{
dynamic d = new ExpandoObject();
d.test = "test";
new Program().ExtMethod(d.test);
Extension.ExtMethod(new Program(), d.test);
}
}
new Program().ExtMethod(d.test); is throwing a compile time error.
But Extension.ExtMethod(new Program(), d.test); is not causing any error.

This is by design, and part of the specification. From the ECMA C# 5 standard, section 12.7.6.3:
In a method invocation (§12.6.6.2) of one of the forms [...] if the normal processing of the invocation finds no applicable methods, an attempt is made to process the construct as an extension method invocation. If expr or any of the args has compile-time type dynamic, extension methods will not apply.
The underlying reason for this is that dynamic binding is intended to give the same result as binding at compile-time would... but for extension methods, that would mean retaining all the using directives at execution time. That would be possible, but I suspect it would be very expensive in terms of invocation performance, and the C# design team decided not to go that way.

You need to cast d.test to an object, in other words write;
new Program().ExtMethod((object)d.test);

Related

Using Reflection to create automatically a List of Delegates

I have a Class called Operations.cs with some method. I want to create a List of Delegates to pick a method randomly. Right now I have the following working solution:
public delegate void Delmethod(ExampleClass supervisor);
public static Operations op = new Operations();
public List<Delmethod> opList = new List<Delmethod>();
opList.Add(op.OpOne);
opList.Add(op.OpTwo);
opList.Add(op.OpThree);
opList.Add(op.OpFour);
opList.Add(op.OpFive);
opList.Add(op.OpSix);
opList.Add(op.OpSeven);
But what I really want is generate the List opList automatically in the case I add a new method in the Operations.cs. I was trying to use reflection in an atempt to solve my problem as follows:
List<MethodInfo> listMethods = new List<MethodInfo>(op.GetType().GetMethods().ToList());
foreach (MethodInfo meth in listMethods)
{
opList.Add(meth);
}
I believe that this doesn't work because I'm making a confusion about the meaning of delegate, but I'm out of ideas.
You have to make a delegate from particular method info.
Assuming, that Operations has only public instance methds with the same signature, the code will look like this:
public static Operations op = new Operations();
public List<Action<ExampleClass>> opList = new List<Action<ExampleClass>>();
oplist.AddRange(op
.GetType()
.GetMethods()
.Select(methodInfo => (Action<ExampleClass>)Delegate.CreateDelegate(typeof(Action<ExampleClass>), op, methodInfo)));
Note, that you don't need to declare Delmethod, since there is Action<T>.

Why does adding beforefieldinit drasticly improve the execution speed of generic classes?

I'm working on a proxy and for generic classes with a reference type parameter it was very slow. Especially for generic methods (about 400 ms vs 3200 ms for trivial generic methods that just returned null). I decided to try to see how it would perform if I rewrote the generated class in C#, and it performed much better, about the same performance as my non-generic class code.
Here is the C# class I wrote:: (note I changed by naming scheme but not a heck of a lot)::
namespace TestData
{
public class TestClassProxy<pR> : TestClass<pR>
{
private InvocationHandler<Func<TestClass<pR>, object>> _0_Test;
private InvocationHandler<Func<TestClass<pR>, pR, GenericToken, object>> _1_Test;
private static readonly InvocationHandler[] _proxy_handlers = new InvocationHandler[] {
new InvocationHandler<Func<TestClass<pR>, object>>(new Func<TestClass<pR>, object>(TestClassProxy<pR>.s_0_Test)),
new GenericInvocationHandler<Func<TestClass<pR>, pR, GenericToken, object>>(typeof(TestClassProxy<pR>), "s_1_Test") };
public TestClassProxy(InvocationHandler[] handlers)
{
if (handlers == null)
{
throw new ArgumentNullException("handlers");
}
if (handlers.Length != 2)
{
throw new ArgumentException("Handlers needs to be an array of 2 parameters.", "handlers");
}
this._0_Test = (InvocationHandler<Func<TestClass<pR>, object>>)(handlers[0] ?? _proxy_handlers[0]);
this._1_Test = (InvocationHandler<Func<TestClass<pR>, pR, GenericToken, object>>)(handlers[1] ?? _proxy_handlers[1]);
}
private object __0__Test()
{
return base.Test();
}
private object __1__Test<T>(pR local1) where T:IConvertible
{
return base.Test<T>(local1);
}
public static object s_0_Test(TestClass<pR> class1)
{
return ((TestClassProxy<pR>)class1).__0__Test();
}
public static object s_1_Test<T>(TestClass<pR> class1, pR local1) where T:IConvertible
{
return ((TestClassProxy<pR>)class1).__1__Test<T>(local1);
}
public override object Test()
{
return this._0_Test.Target(this);
}
public override object Test<T>(pR local1)
{
return this._1_Test.Target(this, local1, GenericToken<T>.Token);
}
}
}
This is compiles in release mode to the same IL as my generated proxy here is the class that its proxying::
namespace TestData
{
public class TestClass<R>
{
public virtual object Test()
{
return default(object);
}
public virtual object Test<T>(R r) where T:IConvertible
{
return default(object);
}
}
}
There was one-exception, I was not setting the beforefieldinit attribute on the type generated. I was just setting the following attributes::public auto ansi
Why did using beforefieldinit make the performance improve so much?
(The only other difference was I wasn't naming my parameters which really didn't matter in the grand scheme of things.
The names for methods and fields are scrambled to avoid collision with real methods.
GenericToken and InvocationHandlers are implementation details that are irrelevant for sake of argument.
GenericToken is literally used as just a typed data holder as it allows me to send "T" to the handler
InvocationHandler is just a holder for the delegate field target there is no actual implementation detail.
GenericInvocationHandler uses a callsite technique like the DLR to rewrite the delegate as needed to handle the different generic arguments passed
)
EDIT::
Here is the test harness::
private static void RunTests(int count = 1 << 24, bool displayResults = true)
{
var tests = Array.FindAll(Tests, t => t != null);
var maxLength = tests.Select(x => GetMethodName(x.Method).Length).Max();
for (int j = 0; j < tests.Length; j++)
{
var action = tests[j];
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
action();
}
sw.Stop();
if (displayResults)
{
Console.WriteLine("{2} {0}: {1}ms", GetMethodName(action.Method).PadRight(maxLength),
((int)sw.ElapsedMilliseconds).ToString(), j);
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
}
private static string GetMethodName(MethodInfo method)
{
return method.IsGenericMethod
? string.Format(#"{0}<{1}>", method.Name, string.Join<Type>(",", method.GetGenericArguments()))
: method.Name;
}
And in a test I do the following::
Tests[0] = () => proxiedTestClass.Test();
Tests[1] = () => proxiedTestClass.Test<string>("2");
Tests[2] = () => handClass.Test();
Tests[3] = () => handClass.Test<string>("2");
RunTests(100, false);
RunTests();
Where Tests is a Func<object>[20], and proxiedTestClass is the class generated by my assembly, and handClass is the one I generated by hand.
RunTests is called twice, once to "warm" things up, and again to run it and print to the screen. I mostly took this code from a post here by Jon Skeet.
As stated in ECMA-335 (CLI cpecification), part I, section 8.9.5:
The semantics of when and what triggers execution of such type
initialization methods, is as follows:
A type can have a type-initializer method, or not.
A type can be specified as having a relaxed semantic for its type-initializer method (for convenience below, we call this relaxed
semantic BeforeFieldInit).
If marked BeforeFieldInit then the type’s initializer method is executed at, or sometime before, first access to any static field
defined for that type.
If not marked BeforeFieldInit then that type’s initializer method is executed at (i.e., is triggered by):
a. first access to any static field of that type, or
b. first invocation of any static method of that type, or
c. first invocation of any instance or virtual method of that type
if it is a value type or
d. first invocation of any constructor for that type.
Also, as you can see from the Michael's code above, the TestClassProxy has only one static field: _proxy_handlers. Notice, that it is used only two times:
In the instance constructor
And in the static field initializer itself
So when BeforeFieldInit is specified, type-initializer will be called only once: in the instance constructor, right before the first access to _proxy_handlers.
But if BeforeFieldInit is omitted, CLR will place the call to the type-initializer before every TestClassProxy's static method invocation, static field access, etc.
In particular, the type-initializer will be called on every invocation of s_0_Test and s_1_Test<T> static methods.
Of course, as stated in ECMA-334 (C# Language Specification), section 17.11:
The static constructor for a non-generic class executes at most once
in a given application domain. The static constructor for a generic
class declaration executes at most once for each closed constructed
type constructed from the class declaration (§25.1.5).
But in order to guarantee this, CLR have to check (in a thread-safe manner) if the class is already initialized, or not.
And these checks will decrease the performance.
PS: You might be surprised that performance issues will gone once you change s_0_Test and s_1_Test<T> to be instance-methods.
First, if you want to learn more about beforefieldinit, read Jon Skeet's article C# and beforefieldinit. Parts of this answer are based on that and I'll repeat the relevant bits here.
Second, your code does very little, so overhead will have significant impact on your measurements. In real code, the impact is likely to be much smaller.
Third, you don't need to use Reflection.Emit to set whether a class has beforefieldint. You can disable that flag in C# by adding a static constructor (e.g. static TestClassProxy() {}).
Now, what beforefieldinit does is that it governs when is the type initializer (method called .cctor) called. In C# terms, type initializer contains all static field initializers and code from the static constructor, if there is one.
If you don't set that flag, the type initializer will be called when either an instance of the class is created or any of the static members of the class are referenced. (Taken from the C# spec, using CLI spec here would be more accurate, but the end result is the same.*)
What this means is that without beforefieldinit, the compiler is very confined about when to call the type initializer, it can't decide to call it a bit earlier, even if doing that would be more convenient (and resulted in faster code).
Knowing this, we can look at what's actually happening in your code. The problematic cases are static methods, because that's where the type initializer might be called. (Instance constructor is another one, but you're not measuring that.)
I focused on the method s_1_Test(). And because I don't actually need it to do anything, I simplified it (to make the generated native code shorter) to:
public static object s_1_Test<T>(TestClass<pR> class1, pR local1) where T:IConvertible
{
return null;
}
Now, let's look at the disassembly in VS (in Release mode), first without the static constructor, that is with beforefieldinit:
00000000 xor eax,eax
00000002 ret
Here, the result is set to 0 (it's done in somewhat obfuscated manner for performance reasons) and the method returns, very simple.
What happens with static the static constructor (i.e. without beforefieldinit)?
00000000 sub rsp,28h
00000004 mov rdx,rcx
00000007 xor ecx,ecx
00000009 call 000000005F8213A0
0000000e xor eax,eax
00000010 add rsp,28h
00000014 ret
This is much more complicated, the real problem is the call instruction, which presumably calls a function that invokes the type initializer if necessary.
I believe this the source of the performance difference between the two situations.
The reason why the added check is necessary is because your type is generic and you're using it with a reference type as a type parameter. In that case, the JITted code for different generic versions of your class is shared, but the type initializer has to be called for each generic version. Moving the static methods to another, non-generic type would be one way to solve the issue.
* Unless you do something crazy like calling instance method on null using call (and not callvirt, which throws for null).

Invoking Method on Object Instantiated From DLL

I am having some trouble with assemblies and DLL's.
instrument_ is declared as an object and I'm creating an instance of "PP150" from the dll whose path is specified by path_.
string className = ContineoProperties.getSingleton().getClassName(path_);
assembly_ = Assembly.LoadFrom(path_);
Type classType = assembly_.GetType("Instrument." + className);
instrument_ = Activator.CreateInstance(classType);
Later I to call the method isntrument_.instrumentCommand(cmd.getCommandName())
The error I get is with when i call the method.
'object' does not contain a definition for 'instrumentCommand'
The isntrument_ is created fine. its just the method call that's giving me a problem. The method does exist in the "PP150.dll". Do I need some DLLImport to allow it to recognize it as a function?
Thanks,
P
If object type is not known in compile time,
To call a method defined on an object, you must use Reflection.
MethodInfo mInfo = classType.GetMethod("instrumentCommand");
mInfo.Invoke(instrument_, new Object[] { _parameters});
The compiler is never going to recognize the methods on a type that you are loading via reflection (e.g. using Assembly.GetType() and Activator.CreateInstance()). Unless you have the type metadata available at build time, you will always get that error if you try to call methods that are not defined on Object itself.
You have two options for making that kind of method call. Both of them require you to give up type safety, the only difference is the amount of work required. In both cases, if you make a mistake, the compiler will not tell you -- you will get a runtime exception instead.
Declare instrument_ as dynamic instead of object. This, obviously, only works in .NET 4.0, but it accomplishes exactly what you're trying to do. The method call will be dispatched at runtime, so as long as the instance that instrument_ references actually has a method call with the appropriate name, it will work.
Use reflection to call the method. You're already using reflection to load the type, so you are halfway there. You would need to add something like this:
// The array of types is the parameter list; assuming instrumentCommand takes
// a string it would look like this:
MethodInfo method = classType.GetMethod("instrumentCommand", new Type[] { typeof(string) });
method.Invoke(instrument_, new object[] { cmd.getCommandName() });
This happens because Activator.CreateInstance returns an object. I would create a separate DLL for the interface which is implemented by the class you want to instantiate. Both the DLL containing this class, and the executable should reference the DLL containing the interface. This way you could cast the object returned by Activator.CreateInstance to the interface, and call its methods:
IInstrument.dll:
interface IInstrument
{
void instrumentCommand(string cmd);
}
Instrument.dll (add IInstrument.dll as reference):
class Instrument : IInstrument
{
public void instrumentCommand(string cmd)
{
// ... implementation ...
}
}
InstrumentApp.exe (add IInstrument.dll as reference):
class Program
{
public static void Main()
{
// ... load Instrument.dll into assembly object ...
// ... load the type from the assembly ...
IInstrument instrument_ = (IInstrument)Activator.CreateInstance(classType);
instrument_.instrumentCommand(cmd.getCommandName());
}
}
The most simple thing would be to link agains PP150.
If you did link against the dll you must use Assembly.LoadFile or Assembly.Load and not LoadFrom because the last one will cause the assembly load to load your assembly in the LoadFrom loader context which will alter type identity.
Suppose you load the Type T from Assembly A via LoadFrom and you link against A as well.
object CreateTypeFrom()
{
var A = Assembly.LoadFrom(#"xxxx");
return A.CreateInstance("T");
}
void Test()
{
object t = CreateTypeFrom();
T RealT = new T(); // no prob
T Castedt = (T)t; // this will throw an InvalidCastException
T isNull = t as T; // this will result in a null instance
}
As you can see although you did create two times an instance of T they cannot be casted to due to different loader context which will make the type pretty useless.
To get rid of these things you could simply use Reflection to create a proxy type which will forward your calls to the proxy type. If you are using .NET 4 you can take advantage of the DLR to find the best matching methods at runtime. The code below creats a Version object and returns it as dynamic object. Then I do call the Major property to an integer and print it out to console. This does work with no exceptions nor compile time errors if you are using .NET 4 or later.
dynamic CreateTypeFrom()
{
var assembly = typeof(string).Assembly;
return assembly.CreateInstance("System.Version", true, BindingFlags.CreateInstance, null, new object[] { 1, 2, 3, 4 }, null, null);
}
[TestMethod]
public void Test()
{
var t = CreateTypeFrom();
int major = t.Major;
Console.WriteLine(major);
}

C# compiler oddity with delegate constructors

Based on the following question, I found some odd behaviour of the c# compiler.
The following is valid C#:
static void K() {}
static void Main()
{
var k = new Action(new Action(new Action(K))));
}
What I do find strange is the compiler 'deconstructing' the passed delegate.
The ILSpy output is as follows:
new Action(new Action(new Action(null, ldftn(K)), ldftn(Invoke)).Invoke);
As one can see, it automatically decides to use the Invoke method of the delegate. But why?
As it is, the code is unclear. Do we have a triply-wrapped delegate (actual) or is the inner delegate just 'copied' to the outer ones (my initial thought).
Surely if the intent was like the compiler emitted the code, one should have written:
var k = new Action(new Action(new Action(K).Invoke).Invoke);
Similar to the decompiled code.
Can anyone justify the reason for this 'surprising' transformation?
Update:
I can only think of one possible use-case for this; delegate type conversion. Eg:
delegate void Baz();
delegate void Bar();
...
var k = new Baz(new Bar( new Action (K)));
Perhaps the compiler should emit a warning if the same delegate types are used.
The spec (section 7.6.10.5) says:
The new delegate instance is initialized with the same invocation list as the delegate instance given by E.
Now suppose the compiler translated it to something similar to your suggestion of:
new Action( a.Target, a.Method)
That would only ever create a delegate with an invocation list of a single method call. For a multi-cast delegate, it would violate the spec.
Sample code:
using System;
class Program
{
static void Main(string[] args)
{
Action first = () => Console.WriteLine("First");
Action second = () => Console.WriteLine("Second");
Action both = first + second;
Action wrapped1 =
(Action) Delegate.CreateDelegate(typeof(Action),
both.Target, both.Method);
Action wrapped2 = new Action(both);
Console.WriteLine("Calling wrapped1:");
wrapped1();
Console.WriteLine("Calling wrapped2:");
wrapped2();
}
}
Output:
Calling wrapped1:
Second
Calling wrapped2:
First
Second
As you can see, the real behaviour of the compiler matches the spec - your suggested behaviour doesn't.
This is partly due to the somewhat odd "sometimes single-cast, sometimes multi-cast" nature of Delegate, of course...
When you try to treat a delegate as a method, the compiler actually uses the delegate's Invoke() method. So, for example, the two lines below compile to the exact same IL (both call Invoke()):
k();
k.Invoke();
I assume the oddity you're seeing is a consequence of this. The delegate constructor expects a method (or rather, a method group), but it gets a delegate instead. So it treats it as a method and uses the Invoke() method.
As for the meaning, it is delegate that calls delegate that calls the actual method. You can verify this yourself by accessing the delegate's Method and Target properties. In the case of the outer-most delegate, Method is Action.Invoke and Target the inner delegate.
delegate is a class
Action delegate has a constructor like so
public extern Action(object #object, IntPtr method);
Since K is a static method there is no need to pass object to inner most action instance as first argument and hence it passes null
Since second argument is pointer to function therefore it passes pointer of K method using ldftn function
for the remaining Action instances the object is passed is inner Action and the second parameter is the Invoke method since when you call a delegate you're actually calling the Invoke method
Summary
var action = new Action(K) => Action action = new Action(null, ldftn(K))
new Action(action) => new Action(action, ldftn(Action.Invoke))
I hope this explains what is happening?

Creating extension method using CodeDOM

I'm trying to create an extension method using CodeDOM. There doesn't seem to be any support for them and using ExtensionAttribute (which C# uses internally to mark extension methods) is not allowed.
It's possible to use a trick to specify the this modifier, but how do I make the containing class static, so that the code actually compiles?
Since static is a C# concept, it's not exposed through the CodeDOM API. And setting TypeAttributes to TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.Public doesn't work, because
an abstract class cannot be sealed or static
How do I make the extension method to compile?
I'm pretty sure you're looking for:
var staticClass = new CodeTypeDeclaration("Extensions")
{
Attributes = MemberAttributes.Public|MemberAttributes.Static
};
However, this appears not to work. Interestingly enough:
provider.Supports(GeneratorSupport.StaticConstructors);
// True
provider.Supports(GeneratorSupport.PublicStaticMembers);
// True
But yet when you go and output it, no changes even though the Attributes property clearly changes from 0x00005002 to 0x00006003.
Per Microsoft Connect this is not possible:
Thanks for reporting this. Unfortunately, it doesn't look like we can support static classes for CodeDom.
The reason is that one of the design goals of CodeDom is to be language-independent, so that any code generated for one language can easily be generated for a different language. While static classes are used often in C#, VB does not support them. Therefore, adding support for static classes will mean that some code that can compile for C# won't be compilable for VB, which goes against our goals.
While we can't act on this issue, we ask that you please continue to provide feedback in the future to help us improve.
A dirty workaround:
var type = new CodeTypeDeclaration("Extensions");
type.Attributes = MemberAttributes.Public;
type.StartDirectives.Add(
new CodeRegionDirective(CodeRegionMode.Start, "\nstatic"));
type.EndDirectives.Add(
new CodeRegionDirective(CodeRegionMode.End, String.Empty));
Produces:
#region
static
public class Extensions
{
}
#endregion
Which compiles.
Instead of compiling the CodeCompileUnit directly, you could get the source code, replace class Extensions with static class Extensions and compile that code.
Cleaned up the hack provided by sixlettervariables a little: placed it into a static method, as mentioned in the discussion.
public static void MarkAsStaticClassWithExtensionMethods(this CodeTypeDeclaration class_)
{
class_.Attributes = MemberAttributes.Public;
class_.StartDirectives.Add(new CodeRegionDirective(
CodeRegionMode.Start, Environment.NewLine + "\tstatic"));
class_.EndDirectives.Add(new CodeRegionDirective(
CodeRegionMode.End, string.Empty));
}
You can get your code to compile exactly how your want it by converting it directly into a string, and then hacking it:
private static CodeSnippetTypeMember CreateStaticClass(CodeTypeDeclaration type)
{
var provider = CodeDomProvider.CreateProvider("CSharp");
using (var sourceWriter = new StringWriter())
using (var tabbedWriter = new IndentedTextWriter(sourceWriter, "\t"))
{
tabbedWriter.Indent = 2;
provider.GenerateCodeFromType(type, tabbedWriter, new CodeGeneratorOptions()
{
BracingStyle = "C",
IndentString = "\t"
});
return new CodeSnippetTypeMember("\t\t" + sourceWriter.ToString().Replace("public class", "public static class"));
}
}

Categories