This may have been answered before. I see many "dynamic method overload resolution" questions, but none that deal specifically with passing a dynamic argument. In the following code, in Test, the last call to M cannot be resolved (it doesn't compile). The error is: the call is ambiguous between [the first two overloads of M].
static void M(Func<int> f) { }
static void M(Func<string> f) { }
static void M(Func<dynamic> f) { }
static dynamic DynamicObject() {
return new object();
}
static void Test() {
M(() => 0);
M(() => "");
M(() => DynamicObject()); //doesn't compile
}
Why, since the type isn't statically known, does it not resolve to the overload accepting dynamic?
Is it even possible for an overloaded method to use dynamic?
What is the best way to resolve this?
The problem here is type inference. The compiler is trying to find out which overload to use based on the argument, but it's also trying to find out what the type of the argument is based on the chosen overload. In the case of M(() => DynamicObject()), the process goes something like this:
The argument to the method is a lambda with zero parameters. This gives us all three overloads as possibilities.
The body of the lambda returns dynamic. Because there is an implicit conversion from dynamic to any other type, we now know all three overloads are good.
Try choosing the best overload. In most cases, “best” means the most derived type. Because both int and string derive from object, the overloads with int and string are considered best.
We now have two “best” overloads, which means the compiler can't actually choose one of them. The compilation fails.
Now, regarding possible solutions to your problem:
Make the type of the lambda explicit, either using cast or typed local variable:
M((Func<dynamic>)(() => DynamicObject()));
or
Func<dynamic> f = () => DynamicObject();
M(f);
Rename the dynamic overload to something like DynamicM. This way, you don't have to deal with overload resolution.
This one feels somewhat wrong to me: make sure the dynamic overload is the only one that fits, by casting to object:
M(() => (object)DynamicObject())
From the definition in MSDN:
dynamic
Type dynamic behaves like type object in most circumstances. However,
operations that contain expressions of type dynamic are not resolved
or type checked by the compiler. The compiler packages together
information about the operation, and that information is later used to
evaluate the operation at run time. As part of the process, variables
of type dynamic are compiled into variables of type object. Therefore,
type dynamic exists only at compile time, not at run time
So dynamic doesn't exist when you compile, cause it needs to convert it into destination *type*, and that's why is not able to resolve it. What is destination type ?
In fact if you do something like this:
static void M(Func<int> f) { }
static void M(Func<string> f) { }
static void M(Func<object> f) { } // could be also declared like dynamic here, works by the way
static object DynamicObject()
{
return new object();
}
static void Test()
{
M(() => 0);
M(() => "");
M(() => DynamicObject());
}
It perfectly works as you want, as object is present like a type already at compile time, in difference of dynamic type which have to be converted.
Related
I want to write a function that takes a function as an argument and then do different things based on whether the passed-in function returns void vs a value.
C# signature checking can't tell the difference so I'm stuck doing it in code.
Is there an easy way to test whether an arbitrary function returns void?
To be clear. I explicitly am not interested in a compile error. I just want the equivalent of what I can do for any other object.
void IsString(object o) => o is string;
void ElseWhere() {
object o = 1;
if (IsString(o)) Bla();
However even this gets a compile error claiming the two methods are ambiguous. It doesn't flag the methods themselves ambiguous but I get an error on the call saying it can't resolve between them.
private static bool HasNoReturnValue(Action o) => true;
private static bool HasNoReturnValue(Func<object> o) => false;
...
if (HasNoReturnValue(SomeFunction)) Bla();
As do anything I've tried involving typeof:
if (SomeFunction is typeof(Func(object>)) Bla();
Let's say you have two methods, one of which returns a Boolean and one which returns void.
void SomeFunction1()
{
}
bool SomeFunction2()
{
return false;
}
To pass either of these as a pointer to a method, you have to convert them to a delegate. Two types of delegates: Action and Func<bool>, respectively:
var action1 = new Action(SomeFunction1);
var action2 = new Func<bool>(SomeFunction2);
You can then write two methods that accept these types as arguments:
void AcceptDelegate(Action action)
{
Console.WriteLine("The delegate returns void.");
}
void AcceptDelegate(Func<bool> func)
{
Console.WriteLine("The delegate returns a Boolean.");
}
And call them like this:
AcceptDelegate(action1);
AcceptDelegate(action2);
Or you could pass the method group directly and the compiler will figure out the type (Why? See the Microsoft documentation on c# method group conversions):
AcceptDelegate(SomeFunction1);
AcceptDelegate(SomeFunction2);
Either way you call them, you would get this output:
The delegate returns void.
The delegate returns a Boolean.
The reason this works is the compiler will automatically pick the right one at compile-time, based on the type of the delegate, just as it would pick the overload for any type such as string or integer. This is the type-safe / early-bound way to do it.
If you insist on an "any delegate"/ late binding sort of approach, you could do something like this:
void AcceptAnyDelegate(Delegate anyAction)
{
Console.WriteLine("The function returns a {0}", anyAction.Method.ReturnType);
}
Because the signature isn't type specific, you have to pass the specific delegates this time (Why? See this answer):
AcceptAnyDelegate(action1);
AcceptAnyDelegate(action2);
And the output would be:
The function returns a Void
The function returns a Boolean
Edit
After rereading your comments, I believe the confusion here is due to a misunderstanding of method groups and delegates.
When you write something like this:
Foo(Bar);
...it appears you believe you are passing to Foo a direct reference to the Bar method. That is not correct. What you are doing is specifying a method group, which the compiler can then use to infer the type of delegate to pass. If Bar is a method with no inputs or outputs, the above code is exactly the same as
Foo(new Action( Bar ));
...only the creation of the delegate is hidden from you by the compiler.
All delegates are specifically typed with respect to their parameters and return type. The Delegate base type is abstract and cannot exist in concrete form. So there is no such thing as passing a type-agnostic function reference-- it doesn't exist in c#.
If you really really want to pass something that is type-agnostic, you can ask the caller to pass a lambda expression:
Foo( () => SomeFunction1() );
You could then parse the expression to figure out the method's inputs and outputs:
void Foo(Expression<Action> anyAction)
{
var mce = anyAction.Body as MethodCallExpression;
var method = mce.Method;
Console.WriteLine("The method has a return type of {0}", method.ReturnType.Name);
}
Then to invoke the expression you would use:
var compiled = anyAction.Compile();
compiled();
That is the closest you're going to get.
There's two different types here:
Action for no return type
and
Func for a return type
Can you make two different signatures for these two different argument types?
This will do the trick
public static void TakeInAFunc<T>(T aFuncOrAction)
{
if (typeof(T) == typeof(Func<>))
{
// some value returned.
}
else if (typeof(T) == typeof(Action<>))
{
// it returns void.
}
}
private static Matcher<T> EqualTo<T>(T item)
{
return new IsEqual<T>(item);
}
How do I modify the above method definition such that the following are valid/allowed.
EqualTo("abc");
EqualTo(4);
EqualTo(null); // doesn't compile. EqualTo<string>(null) does
Trying to port some Java code where null seems to be acceptable value for a T parameter.
Update
Thanks: for all the answers - especially Eamon and Jason. I didn't want the method calls to bother with type-inference. The following overload fixed it.
private static Matcher<object> EqualTo(object item)
{
return EqualTo<object>(item);
}
Actually the above question was a part of a larger puzzle. The end goal was for the following to work.
this.AssertThat(null, EqualTo(null));
this.AssertThat(null, Not(EqualTo("hi")));
this.AssertThat("hi", Not(EqualTo(null)));
Applied the same fix.. RFC. (Ignore the ugly extension method part - that's another problem. Wanted to have these methods in all test-fixtures without inheritance.)
public static void AssertThat<T>(this object testFixture, object actual, Matcher<T> matcher, string message = "")
{
AssertThat(anyObject, (T)actual, matcher, message);
}
public static void AssertThat<T, TSuper>(this object testFixture, T actual, Matcher<TSuper> matcher, string message = "") where T : TSuper
{
... check and assert
Consider the following method:
public bool IsNullString<T>(T item) {
return typeof(T) == typeof(string) && item == null;
}
Yes, this is a pathetically stupid method and using generics is pointless here, but you'll see the point in a moment.
Now consider
bool first = IsNullString<string>(null);
bool second = IsNullString<Foo>(null);
bool third = IsNullString(null);
In the first and second, the compiler can clearly distinguish the type of T (no inference is needed). In the third, how the compiler infer what T is? In particular, it can't distinguish between T == string and T == Foo, or any other type for that matter. Therefore, the compiler has to give you a compile-time error.
If you want to get around this, you either need to cast null
EqualTo((object)null);
or explicitly state the type
EqualTo<object>(null)
or define an overload
private static Matcher<object> EqualTo(object item) {
return new IsEqual<object>(item);
}
Not possible without explicitly specifying a T or doing a cast. Generics are compile time constructs and as such if the compiler can't figure out the type at compile time, then it won't compile (as you're seeing).
Since you can't do exactly what you are wanting to do, how about defining an EqualTo(object) overloaded method? That should allow your required syntax.
You may work around this limitation by using the following syntax:
EqualTo("abc");
EqualTo(4);
EqualTo(default(object));
//equivalently:
EqualTo((object)null);
default(T) is the value a field of type T has if not set. For reference types, it's null, for value types it's essentially memory filled with zero bytes (...which may mean different things for different types, but generally means some version of zero).
I try to avoid the null everywhere in my code nowadays. It hampers type inference elsewhere too, such as with the var declared field and in a ternary operator. For example, myArray==null ? default(int?) : myArray.Length is OK, but myArray==null ? null : myArray.Length won't compile.
Maybe implementing a non-generic EqualTo, which takes an Object as the argument type, would solve the issue of rewriting those code lines.
Many LINQ methods take the form of
MethodName<Type>();
It appears that when calling these methods the Type is optional. For example, these two statements seem to produce identical results:
var a = someStringList.First<string>();
var b = someStringList.First();
Why would I want to type out the <string> portion of that statement? Are there cases where it has utility?
First of all, note that this applies to any generic method, not just LINQ methods.
In general, you do not need to specify the type on generic method, because, usually, the type can be inferred from usage. For example:
T SomeFunc<T>(T arg) {....}
var x = SomeFunc("Hello World");
Since we used a string for the parameter, the compiler decide that T is a string, and therefore we concludes that the method will return a string.
Other times, it cannot deduce it:
T SomeOtherFunc<T>(string arg) {....}
var x = SomeOtherFunc("Hello World"); // error : cannot infer type
IN these case, you have to specify the type:
var x = SomeOtherFunc<int>("Hello World"); // x will be an int.
If you really want to, say for added clarity, you could specify the type even when it can be deduced, but it must be correct:
T SomeFunc<T>(T arg) {....}
var x = SomeFunc<string>("Hello World"); // OK
var y = SomeFunc<int>("Hello World"); // Error
FInally, remember, that for extension methods, like First<> in your example, the object is actually the first parameter, so that can be used in type inference. First<> would be defined as:
public static T First<T>(this IEnumerable<T> coll) ;
Because in the second one type is inferred by the compiler automatically based on the type of someStringList.Since it is an IEnumerable<string> compiler resolves the generic argument type as string.
Ok, so it sounds like it could be used to cast if needed...why not use .Cast?
Because Cast method takes a non-generic IEnumerable as it's first parameter so there is no way to infer the type and that's why you need to provide it.
Consider the following code:
static void Main()
{
dynamic a = 1;
int b = OneMethod(a);
}
private static string OneMethod(int number)
{
return "";
}
Please notice that type of b and return type of OneMethod does not match. Nevertheless it builds and throws the exception at runtime. My question is that why does the compiler let this? Or what is the philosophy behind this?
The reason behind this may be Compiler does not know which OneMethod would be called, because a is dynamic. But why it cannot see that there is only one OneMethod. There will surely be an exception at runtime.
Any expression that has an operand of type dynamic will have a type of dynamic itself.
Thus your expression OneMethod(a) returns an object that's typed dynamically
so the first part of your code is equivalent to
static void Main()
{
dynamic a = 1;
dynamic temp = OneMethod(a);
int b = temp;
}
one way of argue why this is sensible even in your case depends on whether or not you think the compiler should change behavior for that particular line depending when you add the below method
private static T OneMethod<T>(T number)
Now the compiler won't know the type returned until runtime. It won't even know which method is called. The generic or the non generic. Wouldn't you be surprised if it in the first case marked the assignment as a compile error and then by adding a completely different method it got moved to a runtime error?
In C# I am trying to write code where I would be creating a Func delegate which is in itself generic. For example the following (non-Generic) delegate is returning an arbitrary string:
Func<string> getString = () => "Hello!";
I on the other hand want to create a generic which acts similarly to generic methods. For example if I want a generic Func to return default(T) for a type T. I would imagine that I write code as follows:
Func<T><T> getDefaultObject = <T>() => default(T);
Then I would use it as
getDefaultObject<string>() which would return null and if I were to write getDefaultObject<int>() would return 0.
This question is not merely an academic excercise. I have found numerous places where I could have used this but I cannot get the syntax right. Is this possible? Are there any libraries which provide this sort of functionality?
Well you can't overload anything based only on the return value, so this includes variables.
You can however get rid of that lambda expression and write a real function:
T getDefaultObject<T>() { return default(T); }
and then you call it exactly like you want:
int i=getDefaultObject<int>(); // i=0
string s=getDefaultObject<string>(); // s=null
Though one might find practical workarounds like Stephen Cleary's
Func<T> CreateGetDefaultObject<T>() { return () => default(T); }
where you can specify the generics directly, this is a quite interesting problem from a theoretical point that cannot be solved by C#'s current type system.
A type which, as you call it, is in itself generic, is referred to as a higher-rank type.
Consider the following example (pseudo-C#):
Tuple<int[], string[]> Test(Func<?> f) {
return (f(1), f("Hello"));
}
In your proposed system, a call could look like that:
Test(x => new[] { x }); // Returns ({ 1 }, { "Hello" })
But the question is: How do we type the function Test and it's argument f?
Apparently, f maps every type T to an array T[] of this type. So maybe?
Tuple<int[], string[]> Test<T>(Func<T, T[]> f) {
return (f(1), f("Hello"));
}
But this doesn't work. We can't parameterize Test with any particular T, since f should can be applied to all types T. At this point, C#'s type system can't go further.
What we needed was a notation like
Tuple<int[], string[]> Test(forall T : Func<T, T[]> f) {
return (f(1), f("Hello"));
}
In your case, you could type
forall T : Func<T> getDefaultValue = ...
The only language I know that supports this kind of generics is Haskell:
test :: (forall t . t -> [t]) -> ([Int], [String])
test f = (f 1, f "hello")
See this Haskellwiki entry on polymorphism about this forall notation.
This isn't possible, since a delegate instance in C# cannot have generic parameters. The closest you can get is to pass the type object as a regular parameter and use reflection. :(
In many cases, casting to dynamic helps remove the pain of reflection, but dynamic doesn't help when creating new instances, such as your example.
You can't do this, because generic type parameters have to be known at runtime. You have to use the activator class:
Object o = Activator.CreateInstance(typeof(StringBuilder));
which will do exactly what you want to. You can write it as the following:
public T Default<T>()
{
return (T)Activator.CreateInstance(typeof(T));
}
Edit
Blindy's solution is better.