Why can't I implicitly cast a Delegate with Extension methods? - c#

I'm trying to figure out a way to automatically cast something to an Action or Func and the best I can come up with is something like this:
[TestFixture]
public class ExecutionTest
{
public void BadMethod()
{
throw new Exception("Something bad happened");
}
[Test]
public void TestBadMethod()
{
// Want this, but it won't work!!
// BadMethod.Execute().IgnoreExceptions();
// Ick
((Action)BadMethod).Exec().IgnoreExceptions();
// Still ick
((Action)BadMethod).IgnoreExceptions();
// Do not want
ExtensionMethods.Exec(BadMethod).IgnoreExceptions();
// Better but still meh
this.Exec(BadMethod).IgnoreExceptions();
}
}
public static class ExtensionMethods
{
public static Action Exec(this Action action)
{ return action; }
public static Action Exec(this object obj, Action action)
{ return action; }
public static void IgnoreExceptions(this Action action)
{
try { action(); }
catch {}
}
}
There has to a better/easier way to do this, any thoughts?

In C#, when you use the method name without parenthesis, it's called a method group and it has no representation other than at compile time. A method group can represent more than one method (because of overloads and overrides), therefore to implicitly identify which method is needed, a target delegate type must be provided.
In your case, you are wondering why the extension method parameter type won't trigger the resolution of the function. Simply put, extension are evaluated after the type is known, that is, the this parameter can't be used as an implicit conversion target.
Example of why it would break:
class Test
{
void M (void) // Fits Action delegate
{
}
int M (int) // Fits Func<int,int> delegate
{
return 5;
}
void Test()
{
M.Exec(); // UHOH!!! Which Exec to resolve to ???
}
}
public static class Extensions
{
public static void Exec(this Action action) { }
public static void Exec(this Func<int, int> func) { }
}
As you can see, there is a conflict, but as a matter of fact, the conflict never happens because C# won't even try to find a matching extension with a method group.
Note how this won't work either:
class A
{
public static implicit operator int (A a)
{
return 5;
}
void F()
{
A a = new A();
a.Blah(); // Error! It won't implicitly try C.Blah()
}
}
public static class C
{
public static void Blah (int i)
{
}
}
C# won't match A to C.Blah(int) because it would require an implicit conversion.

As Coincoin says, it's not gonna work well in C# because of the overzealous love for method overloading. The only workaround I've seen people use is to create Action and Func methods:
public Action Action(Action f) { return f; }
public Action<A> Action<A>(Action<A> f) { return f; }
...
public Func<A,B,C,D,E> Func(Func<A,B,C,D,E> f) { return f; }
You could even call them all "F" to get some sort of short syntax:
F(BadMethod).NoExceptions();
You might decide to not define these methods in your class, and put them in a Funcs utility or something. Alias it with F and it doesn't end up too bad:
F.F(BadMethod).NoException();
But overall it still sucks :(.

F# lets you do this kind of thing very naturally by providing a much better type inference system.

Related

Call a function and her params in other params function

I'm trying to do this.
void Test(int num)
{
}
Function(Test(1)); //Error
How write my function to allow this ?
I'm tried this but it doesn't work.
void Function(Action<int> action);
It only work if I don't precise the integer like this.
Function(Test); //Compile but I can't precise the integer
Thank you
How write my function to allow this ?
Change the definition of Function as
void Function(Action action);
Now, you can call it
Function(()=>Test(1))
If you can not change the defintion of Function you can call it as
Function((_)=>Test(1))
This Function(Test(1)); Isn't a valid C# syntax, using () is basically invoking the function, not passing it.
You can only do that when the function is expecting a type, and that function is return it.
Func and Action, Are a pre-defined delegetes that you can use without defining your own.
Like this :
public static void Test(int i)
{
Console.WriteLine("Test()");
}
public static int GetNumber()
{
return 5;
}
Test(GetNumber());
If you want to pass a function to another function, there are numerous ways of doing it, Depends on if the function requires parameters or not, if it has a return type or not.
One parameter and no return type
public static void PrintNumber(int num)
{
Console.WriteLine(num);
}
public static void Function(Action<int> predicate, int param)
{
predicate(param);
}
Function(PrintNumber,5);
One parameter and a return type
public static int Test(int num)
{
return num ;
}
public static void Function(Func<int,int> predicate, int param)
{
predicate(param);
}
Function(Test, 5);
The first int of this Func<int,int> is the parameter type, you have can up to 15 i think plus one which is the last one which is the return type.
From here you can google the rest, Hope this helps :)

C# extension method for a method group

I want to implement an extension method for a method. Consider the following code sample (http://dotnetfiddle.net/HztiOo) :
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
A a = new A();
// Noticed that Next() is called twice
Console.WriteLine(a.Next(1));
Console.WriteLine(a.Next(1));
// Works
var withCache = ((Func<int,int>)a.Next).AddCaching();
withCache = new Func<int,int>(a.Next).AddCaching();
withCache = ExtensionMethods.AddCaching<int,int>(a.Next);
// Doesn't work :(
// withCache = a.Next.AddCaching<int,int>();
// Func<int,int> withCache = a.Next.AddCaching();
// Notice that Next() is only called once
Console.WriteLine(withCache(1));
Console.WriteLine(withCache(1));
}
}
public class A
{
public int Next(int n)
{
Console.WriteLine("Called Next("+n+")");
return n + 1;
}
}
public static class ExtensionMethods
{
public static Func<TKey,TVal> AddCaching<TKey,TVal>(this Func<TKey,TVal> fetcher)
{
var cache = new Dictionary<TKey, TVal>();
return k =>
{
if (!cache.ContainsKey(k)) cache[k] = fetcher(k);
return cache[k];
};
}
}
I would like to be able to call the extension method without an explicit cast. In both "doesn't work" examples above, the type system should be able to figure out which overload to use on its own...
Why can't I just use a.Next.AddCaching<int,int>() ?
Note: this is just an example, I am not interested in discussing the best way to add a cache to a method invocation, as there are many other possibilities for this kind of extensions.
According to Eric Lippert blog method group is typeless expression. And you can't do anything, just deal with it.
That's exact reason why you can't implicitly cast it to specific delegate and add extension method to it
You can achieve something stylistically similar to what you are looking for by exposing you method as a Func, as follows (https://dotnetfiddle.net/BTyJdU). Obviously this involves modifying the class, so it can't be achieved with an extension method only.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
A a = new A();
// Noticed that Next() is called twice
Console.WriteLine(a.Next(1));
Console.WriteLine(a.Next(1));
// Works now :)
var withCache = a.Next.AddCaching<int,int>();
withCache = a.Next.AddCaching();
// Notice that Next() is only called once
Console.WriteLine(withCache(1));
Console.WriteLine(withCache(1));
}
}
public class A
{
public Func<int,int> Next;
public A()
{
Next = NextInternal;
}
private int NextInternal(int n)
{
Console.WriteLine("Called Next("+n+")");
return n + 1;
}
}
public static class ExtensionMethods
{
public static Func<TKey,TVal> AddCaching<TKey,TVal>(this Func<TKey,TVal> fetcher)
{
var cache = new Dictionary<TKey, TVal>();
return k =>
{
if (!cache.ContainsKey(k)) cache[k] = fetcher(k);
return cache[k];
};
}
}
I've also put together a fiddle which uses extension methods only. It involves calling an extension on the object rather than the method: https://dotnetfiddle.net/XaLndp
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
A a = new A();
// Noticed that Next() is called twice
Console.WriteLine(a.Next(1));
Console.WriteLine(a.Next(1));
// An alternative, that uses extension methods only
var withCache = a.AddCaching<A,int,int>(x => x.Next);
// Notice that Next() is only called once
Console.WriteLine(withCache(1));
Console.WriteLine(withCache(1));
}
}
public class A
{
public int Next(int n)
{
Console.WriteLine("Called Next("+n+")");
return n + 1;
}
}
public static class ExtensionMethods
{
public static Func<TKey,TVal> AddCaching<T,TKey,TVal>(this T wrapped, Func<T,Func<TKey,TVal>> fetcher)
{
var cache = new Dictionary<TKey, TVal>();
return k =>
{
if (!cache.ContainsKey(k)) cache[k] = fetcher(wrapped)(k);
return cache[k];
};
}
}
You are able to write extension methods for delegates. In your example:
Why can't I just use a.Next.AddCaching() ?
In that question, a.Next isn't a type. Extension methods only work for types. Think about it. In your AddCaching extension method, what would you write after this? You need a type. In this case, you used the delegate Func<TKey,TVal>. That means it'll extend that delegate. For you example to compile, you need to write:
((Func<int,int>)a.Next).AddCaching<int,int>()
This will compile properly. Additionally, since you are defining the generic types in the delegate, you can actually call it like this:
((Func<int,int>)a.Next).AddCaching()
It'll know it is using <int,int> from the delegate.
So, you were close, you just needed to cast a.Next to a type, the delegate Func<int,int> for it to compile. It is the same rules that apply to extending any other type in the language.

How do I get the custom attributes of a method from Action<T>?

How can I get the custom attributes of a method from a Action<T> delegate?
Example:
//simple custom attribute
public class StatusAttribute : Attribute
{
public string Message { get; set; } = string.Empty;
}
// an extension methodto wrap MethodInfo.GetCustomAttributes(Type, Bool) with
// generics for the custom Attribute type
public static class MethodInfoExtentions
{
public static IEnumerable<TAttribute> GetCustomAttributes<TAttribute>(this MethodInfo methodInfo, bool inherit) where TAttribute : Attribute
{
object[] attributeObjects = methodInfo.GetCustomAttributes(typeof(TAttribute), inherit);
return attributeObjects.Cast<TAttribute>();
}
}
// test class with a test method to implment the custom attribute
public class Foo
{
[Status(Message="I'm doing something")]
public void DoSomething()
{
// code would go here
}
}
// creates an action and attempts to get the attribute on the action
private void CallDoSomething()
{
Action<Foo> myAction = new Action<Foo>(m => m.DoSomething());
IEnumerable<StatusAttribute> statusAttributes = myAction.Method.GetCustomAttributes<StatusAttribute>(true);
// Status Attributes count = 0? Why?
}
I realize I could do this by using reflection on Foo, but for what I'm trying to create I have to use an Action<T>.
The problem is that the action doesn't directly point at Foo.DoSomething. It points at a compiler-generated method of the form:
private static void <>__a(Foo m)
{
m.DoSomething();
}
One option here would be to change it to an Expression<Action<T>>, then you can dissect the expression tree afterwards and extract the attributes:
Expression<Action<Foo>> myAction = m => m.DoSomething();
var method = ((MethodCallExpression)myAction.Body).Method;
var statusAttributes = method.GetCustomAttributes<StatusAttribute>(true);
int count = statusAttributes.Count(); // = 1
The issue is that the lambda m => m.DoSomething() is not the same as DoSomething. It is a lambda expression which gets compiled into a method call on a compiler-generated method, possibly using a compiler-generated type (though maybe not the latter, since there are no captured local variables).
A very verbose way of getting an Action<Foo> from an instance (non-static) method of the Foo type is this:
var myAction = (Action<Foo>)Delegate.CreateDelegate(
typeof(Action<Foo>),
null, // treat method as static, even though it's not
typeof(Foo).GetMethod("DoSomething", BindingFlags.Instance | BindingFlags.Public)
);
Obviously, that is far from ideal and probably in fact useless in your case; but it's worth knowing ;)
Update: Actually, it just occurred to me you could write a quick extension method to make this easy for any instance method that you want to wrap as a static method (and maintain the "correct" MethodInfo):
public static class ActionEx
{
public static Action<T> ToStaticMethod<T>(this Action action)
{
if (!(action.Target is T))
{
throw new ArgumentException("Blah blah blah.");
}
return (Action<T>)Delegate.CreateDelegate(
typeof(Action<T>),
null,
action.Method
);
}
}
This would allow you to do:
Action<Foo> myAction = new Action(new Foo().DoSomething).ToStaticMethod<Foo>();
Admittedly, it's not as nice as m => m.DoSomething(); but it does give you an Action<T> whose Method property actually references the DoSomething method directly.
Alternately, instead of an Action<T>, you could use an Expression<Action<T>> and get the MethodInfo from that. Note that the syntax looks just the same in this case:
Action<Foo> myAction = m => m.DoSomething();
Expression<Action<Foo>> myExpression = m => m.DoSomething();
But that is a tricky proposition since an arbitrary Expression<Action<T>> is not guaranteed to be as simple as just m => m.DoSomething().
None of previous answers (except #Marc Gravell♦ 's which has no user's code) seems to be compilable :)
So I would propose mine:
private static void CallDoSomething()
{
var f = new Foo();
Action myAction = f.DoSomething;
IEnumerable<StatusAttribute> statusAttributes = myAction.Method.GetCustomAttributes<StatusAttribute>(true);
}

Generic constraints, where T : struct and where T : class

I would like to differentiate between following cases:
A plain value type (e.g. int)
A nullable value type (e.g. int?)
A reference type (e.g. string) - optionally, I would not care if this mapped to (1) or (2) above
I have come up with the following code, which works fine for cases (1) and (2):
static void Foo<T>(T a) where T : struct { } // 1
static void Foo<T>(T? a) where T : struct { } // 2
However, if I try to detect case (3) like this, it does not compile:
static void Foo<T>(T a) where T : class { } // 3
The error message is Type 'X' already defines a member called 'Foo' with the same parameter types. Well, somehow I cannot make a difference between where T : struct and where T : class.
If I remove the third function (3), the following code does not compile either:
int x = 1;
int? y = 2;
string z = "a";
Foo (x); // OK, calls (1)
Foo (y); // OK, calls (2)
Foo (z); // error: the type 'string' must be a non-nullable value type ...
How can I get Foo(z) to compile, mapping it to one of the above functions (or a third one with another constraint, which I have not thought of)?
Constraints are not part of the signature, but parameters are. And constraints in parameters are enforced during overload resolution.
So let's put the constraint in a parameter. It's ugly, but it works.
class RequireStruct<T> where T : struct { }
class RequireClass<T> where T : class { }
static void Foo<T>(T a, RequireStruct<T> ignore = null) where T : struct { } // 1
static void Foo<T>(T? a) where T : struct { } // 2
static void Foo<T>(T a, RequireClass<T> ignore = null) where T : class { } // 3
(better six years late than never?)
You cannot differentiate the type of method to call based only on the constraints, unfortunately.
So you need to define a method in a different class or with a different name instead.
Further to your comment on Marnix's answer, you can achieve what you want by using a bit of reflection.
In the example below, the unconstrained Foo<T> method uses reflection to farm out calls to the appropriate constrained method - either FooWithStruct<T> or FooWithClass<T>. For performance reasons we'll create and cache a strongly-typed delegate rather than using plain reflection every time the Foo<T> method is called.
int x = 42;
MyClass.Foo(x); // displays "Non-Nullable Struct"
int? y = 123;
MyClass.Foo(y); // displays "Nullable Struct"
string z = "Test";
MyClass.Foo(z); // displays "Class"
// ...
public static class MyClass
{
public static void Foo<T>(T? a) where T : struct
{
Console.WriteLine("Nullable Struct");
}
public static void Foo<T>(T a)
{
Type t = typeof(T);
Delegate action;
if (!FooDelegateCache.TryGetValue(t, out action))
{
MethodInfo mi = t.IsValueType ? FooWithStructInfo : FooWithClassInfo;
action = Delegate.CreateDelegate(typeof(Action<T>), mi.MakeGenericMethod(t));
FooDelegateCache.Add(t, action);
}
((Action<T>)action)(a);
}
private static void FooWithStruct<T>(T a) where T : struct
{
Console.WriteLine("Non-Nullable Struct");
}
private static void FooWithClass<T>(T a) where T : class
{
Console.WriteLine("Class");
}
private static readonly MethodInfo FooWithStructInfo = typeof(MyClass).GetMethod("FooWithStruct", BindingFlags.NonPublic | BindingFlags.Static);
private static readonly MethodInfo FooWithClassInfo = typeof(MyClass).GetMethod("FooWithClass", BindingFlags.NonPublic | BindingFlags.Static);
private static readonly Dictionary<Type, Delegate> FooDelegateCache = new Dictionary<Type, Delegate>();
}
(Note that this example is not threadsafe. If you require thread-safety then you'll either need to use some sort of locking around all access to the cache dictionary, or -- if you're able to target .NET4 -- use ConcurrentDictionary<K,V> instead.)
Drop the struct contraint on the first method. If you need to differentiate between value types and classes you can use the type of the argument to do so.
static void Foo( T? a ) where T : struct
{
// nullable stuff here
}
static void Foo( T a )
{
if( a is ValueType )
{
// ValueType stuff here
}
else
{
// class stuff
}
}
Amplifying my comment to LukeH, a useful pattern if one will need to use Reflection to invoke different actions based upon a type parameter (as distinct from the type of an object instance) is to create a private generic static class something like the following (this exact code is untested, but I've done this sort of thing before):
static class FooInvoker<T>
{
public Action<Foo> theAction = configureAction;
void ActionForOneKindOfThing<TT>(TT param) where TT:thatKindOfThing,T
{
...
}
void ActionForAnotherKindOfThing<TT>(TT param) where TT:thatOtherKindOfThing,T
{
...
}
void configureAction(T param)
{
... Determine which kind of thing T is, and set `theAction` to one of the
... above methods. Then end with ...
theAction(param);
}
}
Note that Reflection will throw an exception if one attempts to create a delegate for ActionForOneKindOfThing<TT>(TT param) when TT does not comply with that method's constraints. Because the system validated the type of TT when the delegate was created, one can safely invoke theAction without further type-checking. Note also that if outside code does:
FooInvoker<T>.theAction(param);
only the first call will require any Reflection. Subsequent calls will simply invoke the delegate directly.
Thankfully this kind of messing around is required less from C# version 7.3
See Whats new in C# 7.3 - Its not very explicit, but it now appears to use the 'where' arguments to some extent during overload resolution.
Overload resolution now has fewer ambiguous cases
Also see Selecting C# Version in your visual studio project
It will still see clashes with the following
Foo(x);
...
static void Foo<T>(T a) where T : class { } // 3
static void Foo<T>(T a) where T : struct { } // 3
But will correctly resolve
Foo(x);
...
static void Foo<T>(T a, bool b = false) where T : class { } // 3
static void Foo<T>(T a) where T : struct { } // 3
If you don't need generic parameters and just want to differentiate between these 3 cases at compile time you can use following code.
static void Foo(object a) { } // reference type
static void Foo<T>(T? a) where T : struct { } // nullable
static void Foo(ValueType a) { } // valuetype
With the latest compilers the RequireX approach can be done without introducing extra types and using only nullable ones (see at the sharplab.io):
using System;
using static Foos;
int x = 1;
int? y = 2;
string z = "a";
Foo(x); // OK, calls (1)
Foo(y); // OK, calls (2)
Foo(z); // OK, calls (3)
class Foos
{
public static void Foo<T>(T a, T? _ = null) where T : struct => Console.WriteLine(1); // 1
public static void Foo<T>(T? a) where T : struct => Console.WriteLine(2); // 2
public static void Foo<T>(T a, T? _ = null) where T : class => Console.WriteLine(3); // 3
}
Actually removing the 2nd parameter in the 3rd method also seems to work:
class Foos
{
public static void Foo<T>(T a, T? _ = null) where T : struct => Console.WriteLine(1); // 1
public static void Foo<T>(T? a) where T : struct => Console.WriteLine(2); // 2
public static void Foo<T>(T a) where T : class => Console.WriteLine(3); // 3
}

Overloading methods in C# .NET

A variable of the type Int32 won't be threated as Int32 if we cast it to "Object" before passing to the overloaded methods below:
public static void MethodName(int a)
{
Console.WriteLine("int");
}
public static void MethodName(object a)
{
Console.ReadLine();
}
To handle it as an Int32 even if it is cast to "Object" can be achieved through reflection:
public static void MethodName(object a)
{
if(a.GetType() == typeof(int))
{
Console.WriteLine("int");
}
else
{
Console.ReadLine();
}
}
Is there another way to do that? Maybe using Generics?
Runtime overload resolution will not be available until C# 4.0, which has dynamic:
public class Bar
{
public void Foo(int x)
{
Console.WriteLine("int");
}
public void Foo(string x)
{
Console.WriteLine("string");
}
public void Foo(object x)
{
Console.WriteLine("dunno");
}
public void DynamicFoo(object x)
{
((dynamic)this).Foo(x);
}
}
object a = 5;
object b = "hi";
object c = 2.1;
Bar bar = new Bar();
bar.DynamicFoo(a);
bar.DynamicFoo(b);
bar.DynamicFoo(c);
Casting this to dynamic enables the dynamic overloading support, so the DynamicFoo wrapper method is able to call the best fitting Foo overload based on the runtime type of the argument.
public static void MethodName(object a)
{
if(a is int)
{
Console.WriteLine("int");
}
else
{
Console.WriteLine("object");
}
}
No, the specific overload of a method that is called is determined at compile-time, not at runtime, unless you're using reflection, thus if you've cast your int to an object, the object overload will be called. I don't believe there's any other way to do this, and generics won't do it for you either.
would this not work?
void MethodName<T>(object a){
T item = a as T;
// treat in the manner you require
}
MethodName<object>(1);
MethodName<Int32>(1);
Perhaps:
public static void MethodName(Type t)
{
Console.WriteLine(t.Name);
}
Then call it:
int a = 0;
string b = "";
object c = new object();
MethodName(a.GetType());
MethodName(b.GetType());
MethodName(c.GetType());
Or:
public static void MethodName<T>(T a)
{
Console.WriteLine(a.GetType().Name);
}
And finally:
public static void MethodName<T>()
{
Console.WriteLine(typeof(T).Name);
}
Update:
It comes down to the fact that the language must somehow be able to determine what type you will be dealing at compile time.
You're pretty much stuck with if/else constructs if you're looking to switch on types. The switch statement itself won't work due to polymorphism. If you're using non-primitive objects, than you can usually accomplish this sort of behavior either with polymorphism or interfaces, such that:
public static void MethodName(MyBaseObject obj)
{
Console.WriteLine(obj.MyVirtualFunctionCall());
}
dynamic overloading was an issue until .NET 3.5, but with .NET 4 its very feasible with few lines of code.
public void publish(dynamic queue)
{
publish(queue);
Console.WriteLine("dynamic queue publishing");
}
public void publish(ValidationQueue queue)
{
Console.WriteLine("Validation queue publishing");
}
how to call
foreach (var queue in _vodaQueueDAO.FetchAllReadyQueuesWithHighestPriority())
{
PublishingService.publish(queue);
}
I wrote an implementation for .NET 3.5 where you e.g. can do something like:
object a = 5;
OverloadResolver.Invoke(MethodName, a);
and it would use the int overload.
Works with compiled and cached Lambda expressions so the performance should be ok.
If anybody needs it, mail me, herzmeisterderwelten, who resides at gmail.com

Categories

Resources