In C#, we have var data type but we can't use it as functions return type.
Why this is not possible?
public var myFunction()
{
var = some operations
}
I believe it's partly due to the design of the compiler. Eric Lippert blogged about why fields can't use implicit typing, and I suspect some of the same arguments hold for methods.
But you could easily end up with ambiguity anyway. For example:
var Method1(bool callMethod2)
{
return callMethod2 ? Method2() : null;
}
var Method2()
{
return Method1(false);
}
What should the type be here?
A simpler example:
var Method1(bool throwException)
{
if (!throwException)
{
return Method1(true);
}
throw new Exception("Bang!");
}
Admittedly this sort of ambiguity could simply be disallowed, but I suspect that the design team felt that the added complexity of both design and implementation wasn't worth the benefit. Don't forget that they're running with limited resources - given a choice between var for methods and async/await, I'd pick the latter in a heartbeat. (Admittedly there are other features I'd have picked instead of dynamic, but that's a different matter...)
Note that return type inference is performed for lambda expressions, so the very idea of it isn't crazy. For example:
IEnumerable<string> x = new[] { "x", "y", "z" };
var result = x.Select(s => { return s.Length; }); // Long form
There the compiler infers the complete type of the lambda expression when it performs overload resolution on Select, converting it to a Func<string, int>. It's not inconceivable to apply the same ideas to methods - just complicated.
var is NOT a datatype in C#. That's why you cannot use it as a return parameter. The compiler infers the type at compile time from the right handside of the assignment and bearing in mind that it is known at compile time you need to use the real type as return value. In C# 4.0 you could use the dynamic type:
public dynamic myFunction()
{
var = some operations
}
Related
I have a converter method:
MyPoco Convert(dynamic p) => new MyPoco { A = p.X, B = p.Y };
void Test()
{
dynamic item = new { X = 1, Y = 2 };
var poco = (MyPoco)Convert(item);
}
I have to explictly cast the result to MyPoco, otherwise poco will become a dynamic variable, too.
But, if I inline the Convert method;
void Test()
{
MyPoco Convert(dynamic p) => new MyPoco { A = p.X, B = p.Y };
dynamic item = new { X = 1, Y = 2 };
var poco = Convert(item);
}
I don't need to cast ConvertItem to MyPoco. Is there a reason for this behavior? It should be easy for the compiler to know that Convert return-type is MyPoco, right?
There is a difference between them which could be the reason - local functions don't support overloading. I think it is important - imagine we have two methods with the same name and with different input and output types
static void Main(string[] args)
{
dynamic d = null;
var result = Hello(d);
Console.WriteLine("Hello World!");
}
static string Hello(string s)
{
return s;
}
static int Hello(int i)
{
return i;
}
It means the result may be string or int - we don't know it in compile time.
While for the following code we get the error that local variable or function already declared
static void Main(string[] args)
{
string Hello(string s)
{
return s;
}
int Hello(int s) // error - local variable or function with the same name already declared
{
return s;
}
dynamic d = null;
var result = Hello(d);
Console.WriteLine("Hello World!");
}
We can only write something like this
static void Main(string[] args)
{
string Hello(string s)
{
return s;
}
dynamic d = null;
var result = Hello(d);
Console.WriteLine("Hello World!");
}
So when compiler sees the local Hello(...) call it knows that return type is string.
Upd:
Regarding the compiler ability to infer correct type in case of dynamic.
I think yes, it is possible for compiler to catch such cases - if we know in compile time that there is the only one method,
there is no chance that in runtime another one will appear.
I could imagine e.g. the method we call is in another assembly, and in runtime we loaded newer version which has different signature - with dynamic it will work, but for the, say, private static method with no overloads I think we could infer non-dynamic type.
But I think, it is was decided to implement it that way for the sake of simplicity - it is easier to keep in mind simple rule - everything that touches dynamic - dynamic.
For local functions for simplicity I think it would be easier to also have them dynamic. I think it is just decision made by different people implementing that.
I checked the roslyn source code trying to find information about that.
The place where it is defined is Binder_Invocation.cs, BindMethodGroupInvocation method.
For local function the following method is called
private BoundExpression BindLocalFunctionInvocationWithDynamicArgument(
SyntaxNode syntax,
SyntaxNode expression,
string methodName,
BoundMethodGroup boundMethodGroup,
DiagnosticBag diagnostics,
CSharpSyntaxNode queryClause,
MethodGroupResolution resolution)
{
// Invocations of local functions with dynamic arguments don't need
// to be dispatched as dynamic invocations since they cannot be
// overloaded. Instead, we'll just emit a standard call with
// dynamic implicit conversions for any dynamic arguments. There
// are two exceptions: "params", and unconstructed generics. While
// implementing those cases with dynamic invocations is possible,
// we have decided the implementation complexity is not worth it.
// Refer to the comments below for the exact semantics.
As you can see the also say about overloading, but for the normal method call no any information about the reason
else
{
if (HasApplicableConditionalMethod(resolution.OverloadResolutionResult))
{
// warning CS1974: The dynamically dispatched call to method 'Goo' may fail at runtime
// because one or more applicable overloads are conditional methods
Error(diagnostics, ErrorCode.WRN_DynamicDispatchToConditionalMethod, syntax, methodGroup.Name);
}
// Note that the runtime binder may consider candidates that haven't passed compile-time final validation
// and an ambiguity error may be reported. Also additional checks are performed in runtime final validation
// that are not performed at compile-time.
// Only if the set of final applicable candidates is empty we know for sure the call will fail at runtime.
var finalApplicableCandidates = GetCandidatesPassingFinalValidation(syntax, resolution.OverloadResolutionResult,
methodGroup.ReceiverOpt,
methodGroup.TypeArgumentsOpt,
diagnostics);
if (finalApplicableCandidates.Length > 0)
{
result = BindDynamicInvocation(syntax, methodGroup, resolution.AnalyzedArguments, finalApplicableCandidates, diagnostics, queryClause);
}
else
{
result = CreateBadCall(syntax, methodGroup, methodGroup.ResultKind, analyzedArguments);
}
They create dynamic if there is at least one canditate.
So, as I said, I think it could be done non-dynamic, but the people who implemented it originally kept it dynamic, probably for simplicity.
What you could do in order to find more details is to try to implement the case when no overloading methods, changing the code
if (finalApplicableCandidates.Length > 0)
{
result = BindDynamicInvocation(syntax, methodGroup, resolution.AnalyzedArguments, finalApplicableCandidates, diagnostics, queryClause);
}
by adding the check if Length == 1 then call BindInvocationExpressionContinued instead of BindDynamicInvocation
and run the tests and check if something fails, maybe it helps.(I didn't even manage to get the roslyn project built, dotnet core is a bit weird)
P.S.
According to this
if (boundMethodGroup.TypeArgumentsOpt.IsDefaultOrEmpty && localFunction.IsGenericMethod)
{
Error(diagnostics, ErrorCode.ERR_DynamicLocalFunctionTypeParameter, syntax, localFunction.Name);
return BindDynamicInvocation(
For local function we could get dynamic instead of concrete type.
If you type something like this
static void Main(string[] args)
{
int TestFunc<T>(T data)
{
return 1;
}
dynamic d = 2;
var r = TestFunc(d);
}
Yes, it will give the error, but if you check the inferred type it of r will show dynamic))
When I call a function and replace one of the parameters with dynamic, the compiler inferres the function result to be dynamic. I don't understand why this happens.
Example: the inferred type for a is dynamic, so this code compiles, but of course fails at runtime with RuntimeBinderException:
dynamic b = "";
var a = MethodWithoutOverloads("", b);
a.DoesNotExist();
...
public string MethodWithoutOverloads(string a, string b) { ... }
Somebody knows why the type inferred is not the return type of the function?
EDIT: edited to make clear this happens with methods without overloads
You are right in the sense that the compiler could reason out that all String.Format overloads return a string and therefore infer that a must be a string no matter what b really is.
The truth is that the compiler does not do that. It solves the general case, which is good, and because overloads with different return types are valid in C#, it simply assigns the return type as dynamic and lets the runtime figure it out.
Answering your specific question,
public string MethodWithoutOverloads(string a, string b) { ... }
dynamic a = "";
var result = MethodWithoutOverloads(a, a); // result is dynamic.
Lets imagine the compiler decides that result is string and you publish to the wild west your library. Then, later on, you decide to add an overload with the following signature:
public int MethodWithoutOverloads(int a, int b) { ... }
Now, what should the type of result be? And, what happens to existing code that relied on result being strongly typed to string?
string result = MethodWithoutOverloads(someDynamicVariable, someOtherDynamicVariable);
The semantics change completely; before a consumer had a safe strongly typed variable, now he suddenly has a potentially unsafe implicit cast that can blow up in runtime.
Because the compiler doesn't know which method is going to be invoked at run time.
For example, you may have the two methods:
int MyMethod(int a)
{
return 5;
}
double MyMethod(string a)
{
return 6.0;
}
And you write the following code:
dynamic myThing = 5;
var myResult = MyMethod(myThing);
Considering we've explicitly said myThing is dynamic, and this its type is to be determined at runtime, we have no idea which method will be invoked (if any). Thus, we don't know the return type, either.
I have a method that looks like this (assume that I have the necessary method GetMySerializedDataArry() and my serializer JsonSerializer):
public static List<T> GetMyListOfData<T>()
{
var msgList = new List<T>();
foreach (string s in GetMySerializedDataArray())
{
msgList.Add(JsonSerializer.Deserialize<T>(s));
}
return msgList;
}
This works fine and as expected.
However, I want to use the same method to optionally, if and only if the generic type is specified as string, return the data unserialized like this (which does not compile and has syntax problems):
public static List<T> GetMyListOfData<T>(bool leaveSerialized)
{
if (typeof (T) != typeof(string) && leaveSerialized)
{
throw new ArgumentException("Parameter must be false when generic type is not List<string>", "leaveSerialized");
}
var msgList = new List<T>();
foreach (string s in GetMySerializedDataArray())
{
if (leaveSerialized)
{
// Casting does not work: "Cannot cast expression of type 'System.Collections.Generic.List<T>' to type 'List<string>'"
// I've tried various permutations of "is" and "as"... but they don't work with generic types
// But I know in this case that I DO have a list of strings..... just the compiler doesn't.
// How do I assure the compiler?
((List<string>)msgList).Add(s);
}
else
{
msgList.Add(JsonSerializer.Deserialize<T>(s));
}
}
return msgList;
}
My questions are in the inline comment.... basically though the compiler clearly doesn't like the cast of generic to non-generic, it won't let me use permutations of "is" and "are" operators either, I know I actually have the correct string in this case.... how to assure the compiler it is OK?
Many thanks in advance.
EDIT: SOLUTION
Thanks to Lee and Lorentz, both. I will be creating two public methods, but implementing the code in a private method with the admittedly icky decision tree about whether to leave serialization. My reason is that my real-world method is far more complex than what I posed here to SO, and I don't want to duplicate those business rules.
FINAL EDIT: CHANGED SOLUTION
Although both answers were very helpful, I have now been able to detangle business rules, and as a result the "correct" answer for me is now the first -- two different methods. Thanks again to all.
You should not return a list of strings as a list of T. I would suggest that you use two separate methods and skip the parameter:
public static List<T> GetMyListOfData<T>()
public static List<string> GetSerializedMyListOfData()
The advantages of this approach is
It's more readable (imo) GetSerializedMyListOfData() vs GetMyListOfData<string>(true)
You also know the intent of the caller at compile time and don't have to throw an exception when the type argument don't match the intent to leave the data serialized
You can cast to object first:
((List<string>)(object)msgList).Add(s);
however a cleaner solution could be to create another method for dealing with strings, this would also allow you to remove the leaveSerialized parameter.
I have the following code:
Func<string, bool> comparer = delegate(string value) {
return value != "0";
};
However, the following does not compile:
var comparer = delegate(string value) {
return value != "0";
};
Why can't the compiler figure out it is a Func<string, bool>? It takes one string parameter, and returns a boolean. Instead, it gives me the error:
Cannot assign anonymous method to an
implicitly-typed local variable.
I have one guess and that is if the var version compiled, it would lack consistency if I had the following:
var comparer = delegate(string arg1, string arg2, string arg3, string arg4, string arg5) {
return false;
};
The above wouldn't make sense since Func<> allows only up to 4 arguments (in .NET 3.5, which is what I am using). Perhaps someone could clarify the problem. Thanks.
UPDATE: This answer was written over ten years ago and should be considered to be of historical interest; in C# 10 the compiler will infer some delegate types.
Others have already pointed out that there are infinitely many possible delegate types that you could have meant; what is so special about Func that it deserves to be the default instead of Predicate or Action or any other possibility? And, for lambdas, why is it obvious that the intention is to choose the delegate form, rather than the expression tree form?
But we could say that Func is special, and that the inferred type of a lambda or anonymous method is Func of something. We'd still have all kinds of problems. What types would you like to be inferred for the following cases?
var x1 = (ref int y)=>123;
There is no Func<T> type that takes a ref anything.
var x2 = y=>123;
We don't know the type of the formal parameter, though we do know the return. (Or do we? Is the return int? long? short? byte?)
var x3 = (int y)=>null;
We don't know the return type, but it can't be void. The return type could be any reference type or any nullable value type.
var x4 = (int y)=>{ throw new Exception(); }
Again, we don't know the return type, and this time it can be void.
var x5 = (int y)=> q += y;
Is that intended to be a void-returning statement lambda or something that returns the value that was assigned to q? Both are legal; which should we choose?
Now, you might say, well, just don't support any of those features. Just support "normal" cases where the types can be worked out. That doesn't help. How does that make my life easier? If the feature works sometimes and fails sometimes then I still have to write the code to detect all of those failure situations and give a meaningful error message for each. We still have to specify all that behaviour, document it, write tests for it, and so on. This is a very expensive feature that saves the user maybe half a dozen keystrokes. We have better ways to add value to the language than spending a lot of time writing test cases for a feature that doesn't work half the time and doesn't provide hardly any benefit in cases where it does work.
The situation where it is actually useful is:
var xAnon = (int y)=>new { Y = y };
because there is no "speakable" type for that thing. But we have this problem all the time, and we just use method type inference to deduce the type:
Func<A, R> WorkItOut<A, R>(Func<A, R> f) { return f; }
...
var xAnon = WorkItOut((int y)=>new { Y = y });
and now method type inference works out what the func type is.
Only Eric Lippert knows for sure, but I think it's because the signature of the delegate type doesn't uniquely determine the type.
Consider your example:
var comparer = delegate(string value) { return value != "0"; };
Here are two possible inferences for what the var should be:
Predicate<string> comparer = delegate(string value) { return value != "0"; }; // okay
Func<string, bool> comparer = delegate(string value) { return value != "0"; }; // also okay
Which one should the compiler infer? There's no good reason to choose one or the other. And although a Predicate<T> is functionally equivalent to a Func<T, bool>, they are still different types at the level of the .NET type system. The compiler therefore cannot unambiguously resolve the delegate type, and must fail the type inference.
Eric Lippert has an old post about it where he says
And in fact the C# 2.0 specification
calls this out. Method group
expressions and anonymous method
expressions are typeless expressions
in C# 2.0, and lambda expressions join
them in C# 3.0. Therefore it is
illegal for them to appear "naked" on
the right hand side of an implicit
declaration.
Different delegates are considered different types. e.g., Action is different than MethodInvoker, and an instance of Action can't be assigned to a variable of type MethodInvoker.
So, given an anonymous delegate (or lambda) like () => {}, is it an Action or a MethodInvoker? The compiler can't tell.
Similarly, if I declare a delegate type taking a string argument and returning a bool, how would the compiler know you really wanted a Func<string, bool> instead of my delegate type? It can't infer the delegate type.
The following points are from the MSDN regarding Implicitly Typed Local Variables:
var can only be used when a local variable is declared and initialized in the same statement; the variable cannot be initialized to null, or to a method group or an anonymous function.
The var keyword instructs the compiler to infer the type of the variable from the expression on the right side of the initialization statement.
It is important to understand that the var keyword does not mean "variant" and does not indicate that the variable is loosely typed, or late-bound. It just means that the compiler determines and assigns the most appropriate type.
MSDN Reference: Implicitly Typed Local Variables
Considering the following regarding Anonymous Methods:
Anonymous methods enable you to omit the parameter list.
MSDN Reference: Anonymous Methods
I would suspect that since the anonymous method may actually have different method signatures, the compiler is unable to properly infer what the most appropriate type to assign would be.
My post doesn't answer the actual question, but it does answer the underlying question of :
"How do I avoid having to type out some fugly type like Func<string, string, int, CustomInputType, bool, ReturnType>?" [1]
Being the lazy/hacky programmer that I am, I experimented with using Func<dynamic, object> - which takes a single input parameter and returns an object.
For multiple arguments, you can use it like so:
dynamic myParams = new ExpandoObject();
myParams.arg0 = "whatever";
myParams.arg1 = 3;
Func<dynamic, object> y = (dynObj) =>
{
return dynObj.arg0.ToUpper() + (dynObj.arg1 * 45); //screw type casting, amirite?
};
Console.WriteLine(y(myParams));
Tip: You can use Action<dynamic> if you don't need to return an object.
Yeah I know it probably goes against your programming principles, but this makes sense to me and probably some Python coders.
I'm pretty novice at delegates... just wanted to share what I learned.
[1] This assumes that you aren't calling a method that requires a predefined Func as a parameter, in which case, you'll have to type that fugly string :/
Other answers were correct at the time they were written, but starting from C# 10.0 (from 2021), the compiler can infer a suitable delegate type (like some Func<...>, Action<...> or generated delegate type) in such cases.
See C# 10 Features - Lambda improvements.
var comparer = delegate(string value) {
return value != "0";
}; // OK in C# 10.0, picks 'Func<string, bool>' in this case
Of course the more usual syntax is to us =>, so:
var comparer = (string value) => {
return value != "0";
}; // OK in C# 10.0, picks 'Func<string, bool>' in this case
How is about that?
var item = new
{
toolisn = 100,
LangId = "ENG",
toolPath = (Func<int, string, string>) delegate(int toolisn, string LangId)
{
var path = "/Content/Tool_" + toolisn + "_" + LangId + "/story.html";
return File.Exists(Server.MapPath(path)) ? "<a style=\"vertical-align:super\" href=\"" + path + "\" target=\"_blank\">execute example</a> " : "";
}
};
string result = item.toolPath(item.toolisn, item.LangId);
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.