I've got really simple code:
static void Main(string[] args)
{
var task = Task.Factory.StartNew(GetInt);
var task2 = Task.Factory.StartNew(
() =>
{
return GetInt();
});
}
static int GetInt()
{
return 64;
}
Why do I get a compiler error for the first task?
The method signatures (no params, return type is int) are equal, aren't they?
I know a solution(which is quite simple: var task = Task.Factory.StartNew<int>(GetInt);) but I'd like to know whats the problem with the code above.
You get an ambiguous call error because the method signature is the same.
Return values are not part of the signature.
Since you don't provide an explicit return type, the compiler doesn't know which to take.
Method Signature in C#
Because the compiler cannot decide which of these two overloads to use:
StartNew(Action)
StartNew<TResult>(Func<TResult>)
The reason for that is that the return type is not part of the overload resolution in C# (same way as you can't have two overloads only differing in return types) and therefore the compiler cannot decide whether GetInt should be an Action or a Func<T>. Forcing to use the generic version by calling StartNew<int>(GetInt) will provide the required information.
For the record, here are two more ways of doing it (that compile):
var task3 = Task.Factory.StartNew((Func<int>)GetInt);
var task4 = Task.Factory.StartNew(() => GetInt());
Would help to show the exception: "The call is ambiguous between the following methods or properties: 'System.Threading.Tasks.TaskFactory.StartNew(System.Action)' and 'System.Threading.Tasks.TaskFactory.StartNew(System.Func)'"
If you take a look there are two possible methods:
public Task<TResult> StartNew<TResult>(Func<TResult> function);
public Task StartNew(Action action);
If you add the <int> or supply a Func<int> you force it to take the first signature. Without that your code is ambiguous.
You get the compile error because the StartNew method takes in either an Action (returns void) or a Func (returns something) predicates with it's various overloads, and not a direct delegate.
As stated by others, you need to pass in GetInt as a function to StartNew, or specify that you intend to return a value from StartNew by supplying the generic type. Otherwise, the compiler has no idea what kind of task you intend to create....it is ambiguous.
static void Main(string[] args)
{
var task = Task.Factory.StartNew<int>(GetInt);
var task2 = Task.Factory.StartNew(
() =>
{
return GetInt();
});
}
static int GetInt()
{
return 64;
}
Related
I have the following code:
Func<string, string> func1 = (param) =>
{
Console.WriteLine("Func 1 executing");
return "Hello" + param;
};
Func<string, string> func2 = (param) =>
{
Console.WriteLine("Func 2 executing");
return "World" + param;
};
Func<string, string> funcSum = func1 + func2;
string funcResult = funcSum("!");
Console.WriteLine(funcResult);
The output is:
Func 1 executing
Func 2 executing
World!
Inverting the sum:
Func<string, string> funcSum = func2 + func1;
Gives the output:
Func 2 executing
Func 1 executing
Hello!
My initial test was done with a boolean return type, and the returned value was also always determined by the last function. Is it working as intended? Aren't we losing the return value of the other functions? If so, is there a use case in real world of those multicast delegate of functions?
Is it working as intended?
It's working as specified, at least. Whether that's what you intended or not is a different matter :) From section 15.4 of the C# 5 specification - emphasis mine:
Invocation of a delegate instance whose invocation list contains multiple entries proceeds by invoking each of the methods in the invocation list, synchronously, in order. Each method so called is passed the same set of arguments as was given to the delegate instance. If such a delegate invocation includes reference parameters (§10.6.1.2), each method invocation will occur with a reference to the same variable; changes to that variable by one method in the invocation list will be visible to methods further down the invocation list. If the delegate invocation includes output parameters or a return value, their final value will come from the invocation of the last delegate in the list.
Next:
Aren't we losing the return value of the other functions?
Yes, at the moment.
If so, is there a use case in real world of those multicast delegate of functions?
Very rarely, to be honest. However, you can split a multicast delegate apart, using Delegate.GetInvocationList():
foreach (Func<string, string> func in funcSum.GetInvocationList())
{
Console.WriteLine(func("!"));
}
Most of your question has been answered already, but one thing that's missing is a real-world use case for this. Here's one: asynchronous event handlers.
public delegate Task AsyncEventHandler(object sender, EventArgs e);
public event AsyncEventHandler X;
public async Task OnX(EventArgs e) {
// ...
var #event = X;
if (#event != null)
await Task.WhenAll(
Array.ConvertAll(
#event.GetInvocationList(),
d => ((AsyncEventHandler)d)(this, e)));
}
This allows the user of the class to simply write
myobject.X += async (sender, e) => { ... };
but the object will still ensure that OnX's task doesn't complete until the event handler's has.
The multicast delegate will always return the result of the last function. Because there is no predefined way to combine or chain the T results.
If you want to obtain all the results along the chain, try this :
var result = "!";
foreach (Func<string, string> func in funcSum.GetInvocationList())
{
result = func(result);
}
Is this possible in C#? The following code produces a compiler error.
HashSet<Task<(string Value, int ToNodeId)>> regionTasks =
new HashSet<Task<(string Value, int ToNodeId)>>();
foreach (Connection connection in Connections[RegionName])
{
regionTasks.Add(async () =>
{
string value = await connection.GetValueAsync(Key);
return (value, connection.ToNode.Id);
}());
}
The C# compiler complains, "Error CS0149: Method name expected." It's unable to infer the lambda method's return type.
Note my technique of invoking the lambda method immediately via the () after the the lambda block is closed {}. This ensures a Task is returned, not a Func.
The VB.NET compiler understands this syntax. I am stunned to find an example of the VB.NET compiler outsmarting the C# compiler. See my An Async Lambda Compiler Error Where VB Outsmarts C# blog post for the full story.
Dim regionTasks = New HashSet(Of Task(Of (Value As String, ToNodeId As Integer)))
For Each connection In Connections(RegionName)
regionTasks.Add(Async Function()
Dim value = Await connection.GetValueAsync(Key)
Return (value, connection.ToNode.Id)
End Function())
Next
The VB.NET compiler understands the End Function() technique. It correctly infers the lambda method's return type is Function() As Task(Of (Value As String, ToNodeId As Integer)) and therefore invoking it returns a Task(Of (Value As String, ToNodeId As Integer)). This is assignable to the regionTasks variable.
C# requires me to cast the lambda method's return value as a Func, which produces horribly illegible code.
regionTasks.Add(((Func<Task<(string Values, int ToNodeId)>>)(async () =>
{
string value = await connection.GetValueAsync(Key);
return (value, connection.ToNode.Id);
}))());
Terrible. Too many parentheses! The best I can do in C# is explicitly declare a Func, then invoke it immediately.
Func<Task<(string Value, int ToNodeId)>> getValueAndToNodeIdAsync = async () =>
{
string value = await connection.GetValueAsync(Key);
return (value, connection.ToNode.Id);
};
regionTasks.Add(getValueAndToNodeIdAsync());
Has anyone found a more elegant solution?
If .NET Standard 2.1 (or some .NET Framework versions, see compatibility list) is available for you, you can use LINQ with ToHashSet method:
var regionTasks = Connections[RegionName]
.Select(async connection =>
{
string value = await connection.GetValueAsync(Key);
return (Value: value, ToNodeId: connection.ToNode.Id);
})
.ToHashSet();
Or just initialize HashSet with corresponding IEnumerable.
UPD
Another workaround from linked in comments answer:
static Func<R> WorkItOut<R>(Func<R> f) { return f; }
foreach (Connection connection in Connections[RegionName])
{
regionTasks.Add(WorkItOut(async () =>
{
string value = await connection.GetValueAsync(Key);
return (value, connection.ToNode.Id);
})());
}
When I first read the title of your question I thought "Eh? Who would propose trying to assign a value of type x to variable of type y, not in an inheritance relationship with x? That's like trying to assign an int to a string..."
I read the code, and that changed to "OK, this isn't assigning a delegate to a Task, this is just creating a Task and storing it in a collection of Tasks.. But it does look like they're assigning a delegate to a Task...
Then I saw
Note my technique of invoking the lambda method immediately via the () after the the lambda block is closed {}. This ensures a Task is returned, not a Func.
The fact that you have to explain this with commentary means it's a code smell and the wrong thing to do. Your code has gone from being readably self documenting, to a code golf exercise, using an arcane syntax trick of declaring a delegate and immediately executing it to create a Task. That's what we have Task.Run/TaskFactory.StartNew for, and it's what all the TAP code I've seen does when it wants a Task
You'll note that this form works and doesn't produce an error:
HashSet<Task<(string Value, int ToNodeId)>> regionTasks =
new HashSet<Task<(string Value, int ToNodeId)>>();
foreach (Connection connection in Connections[RegionName])
{
regionTasks.Add(Task.Run(async () =>
{
string value = await connection.GetValueAsync(Key);
return (value, connection.ToNode.Id);
}));
}
It is far more clear how it works and the 7 characters you saved in not typing Task.Run means you don't have to write a 50+ character comment explaining why something that looks like a delegate can be assigned to a variable of type Task
I'd say the C# compiler was saving you from writing bad code here, and it's another case of the VB compiler letting developers play fast an loose and writing hard to understand code
An easy way to invoke asynchronous lambdas in order to get the materialized tasks, is to use a helper function like the Materialize below:
public static Task Materialize(Func<Task> taskFactory) => taskFactory();
public static Task<T> Materialize<T>(Func<Task<T>> taskFactory) => taskFactory();
Usage example:
regionTasks.Add(Materialize(async () =>
{
string value = await connection.GetValueAsync(Key);
return (value, connection.ToNode.Id);
}));
I have several objects of different types with methods taking different parameters that all return the same type. These methods can fail. Is there a way to write a function that will take the object and its method, indicate if the method fails, and indicate the object on which failure occurred? I can't modify the Result object, and it holds no information about the object that called it.
I find this a little verbose:
Result resultA = A.something();
if(resultA.Failed) return new Status{Failed=A.GetType().ToString()};
Result resultB = B.somethingElse(3);
if(resultB.Failed) return new Status{Failed=B.GetType().ToString()};
Result result3 = C.someOtherThing("apple");
if(resultC.Failed) return new Status{Failed=C.GetType().ToString()};
// Do some processing of the results (will succeed if A,B,C succeeded)
return new Status {Failed=null, Success=true};
Is there a way to encapsulate all that into a function? It seems very repetitive. A, B, and C do not inherit from a useful base class, and their methods all take different parameters and have different names.
That being said, I do have access to the Status class, and even the return value of this function. The function need not return, it could throw an exception instead. If there's a failure, the function can break immediately.
I Suggest a small variation to #Shawn Holzworth's answer that is a bit simpler.
First, since the only thing in common to your methods is their return type, this is the only thing that we can generalize here. We can construct a methods that will handle the execution as you requested like so:
public static Status ExecuteRequests(params Func<Result>[] actions){
foreach (Func<Result> action in actions) {
Result r = action();
if (!r.Success) {
Status s = new Status() { Failed = action.Target.GetType().ToString() };
return s;
}
}
return new Status() { Success = true };
}
And the call site:
ExecuteRequests(
() => A.doSomething(),
() => B.doSomethingElse(42));
If you want to perfrom extra computation on the Results, you can extend the ExecuteRequests method to input a handler in the Form of Action.
This abstraction actually facilitates another thing that you did not ask about but I believe is worth mentioning: Parallel execution. When you encapsulate these operations like this, it is very easy to make use of the TPL, to send out the requests in parallel and aggregate them as the arrive, but this is a bit more involved.
Having mentioned the above, I wonder whether this is worth the effort. Indeed it abstracts the execution sequence, but I am not sure that this significantly enhances readability (Unless you have a longer execution sequence than 3, and expect it to grow in the future).
The simplest way is make a new subclass of Status that fills it the Failed property for you, you can just have the constructor take a object in as the type and call GetType() in there.
public class FailedStatus : Status
{
public FailedStatus(object source)
{
this.Failed = source.GetType().ToString();
}
}
Result resultA = A.something();
if(resultA.Failed) return new FailedStatus(A);
Result resultB = B.somethingElse(3);
if(resultB.Failed) return new FailedStatus(B);
Result result3 = C.someOtherThing("apple");
if(resultC.Failed) return new FailedStatus(C);
If Result derives from Status too the least verbose way is modify something(), somethingElse(int), and someOtherThing(string) to set the string itself (but I doubt this is true sense it appears Result.Failed is a bool but Status.Failed is a string).
One simple way you could do this:
//Note: the method signature could just be IEnumerable<Result> AggregateResults(params Func<Result>[])
//if you want to be able to aggregate the results of 0 calls
IEnumerable<Result> AggregateResults(Func<Result> func, params Func<Result>[] otherFuncs)
{
yield return func();
foreach(var otherFunc in otherFuncs)
yield return otherFunc();
}
//Usage:
var results = AggregateResults(
() => A.Something(),
() => B.SomethingElse(3),
() => C.SomethingOtherThing("apple"));
Unfortunately the requirement to stop on the first failing call and get the calling object makes it slightly harder:
class AggregateResult
{
public object CallingObject;
public Result Result;
public static AggregateResult Create<T>(T t, Func<T,Result> func)
{
return new AggregateResult() { CallingObject = t, Result = func(t) };
}
}
IEnumerable<AggregateResult> AggregateResults(Func<AggregateResult> func, params Func<AggregateResult>[] otherFuncs)
{
yield return func();
foreach (var otherFunc in otherFuncs)
yield return otherFunc();
}
//Usage:
var results = AggregateResults(
() => AggregateResult.Create(A, x=>x.Something()),
() => AggregateResult.Create(B, x=>x.SomethingElse(3)),
() => AggregateResult.Create(C, x=>x.SomethingOtherThing("apple")));
var failedResult = results.FirstOrDefault(x => x.Result.Failed);
if (failedResult != null) return new Status() { Failed = failedResult.CallingObject.GetType().ToString() };
That said, I agree with the comments that this sounds like an XY problem.
You could create an extension method for Result that returns null in case of success, like this:
static class ResultExtension
{
public static Status GetStatus<T>(this Result res, T a) {
return res.Failed? new Status{Failed=a.GetType().ToString()} : null;
}
}
then you could chain operations with the null-coalescing operator ?? :
return A.something().GetStatus(A) ??
B.somethingElse(3).GetStatus(B) ??
C.someOtherThing("apple").GetStatus(C) ??
new Status{Failed=null, Success=true};
note that the ?? operator short-circuits, so you only evaluate somethingElse(3) or someOtherThing("apple") if none of the previous results is null (i.e. a failure), as you want and in the end, if and only if all calls succeeded you return a success Status.
I'm working on a method that needs to repeat a small operation at different spots, but the code to be repeated should be private to the method. The obvious solution is a nested function. Whatever I try however, the C# compiler barfs at me.
Something roughly equal to this Perl snippet:
my $method = sub {
$helper_func = sub { code to encapsulate };
# more code
&$helper( called whenever needed );
# more code
}
is what I am talking about, and what I'm trying to accomplish in C#.
No other method in the class should be able to access the helper function in this context. The most logical means of writing this construct in C#, as it appears to me would be something like this:
var helper = (/* parameter names */) => { /* code to encapsulate */ };
And actually make the compiler earn its keep.
Since such an assignment is forbidden, as is the equivalent using the older delegate(){} syntax in place of the lambda, and so is declaring a delegate type within a method—what csc actually allows me to write however, is this:
private delegate /* return type */ Helper(/* parameters */);
private /* return type */ method(/* parameters */) {
Helper helper = (/* parameter names */) => {
/* code to encapsulate */
};
// more code
helper( /* called whenever needed */ );
// more code
}
Which is all fine and dandy for not copy and pasting a chunk of code around and editing the parameters by hand but it leaks a private delegate type to the rest of the class rather than keeping it private to the method. Which defeats the purpose in the first place. Using goto statements and local variables for parameters would provide better encapsulation of "helper" in this context without sacrificing code reuse. If I wanted to simulate function calls by passing parameters through registers, I think would rather use an assembler. I haven't found an acceptable way of refactoring the code to avoid the problem altogether either.
So, is it even possible to force this Common Object Oriented Language to obey?
You actually can do this in C#.
Func<T1, T2, ..., TReturn> myFunc = (a, b, ...) =>
{
//code that return type TReturn
};
If you need an anonymous method of return type void use Action instead of Func:
Action<T1, T2, ...> myAction = (a, b, ...) =>
{
//code that doesn't return anything
};
If you are in C# 3.5 or higher you can take advantage of the lambdas and convenience delegate declarations Func<> and Action<>. So for instance
void DoSomething()
{
Func<int,int> addOne = (ii) => ii +1;
var two = addOne(1);
}
The reason you can't do
var addOne = (ii) => ii +1;
is because of Homoiconicity, the lambda can be interpreted as two different constructs, a delegate and an expression tree. Thus the need to be explicit in declaration.
If you explicitly type it, it will work, i.e.
Action<paramType1, paramType2> helperAction = (/* parameter names */) => { /* code to encapsulate */ };
Func<paramType1, paramType2, returnType> helperFunction = (/* parameter names */) => { /* code to encapsulate */ };
The reason var doesn't work is that a lambda expression can evaluate to multiple types (I believe either a delegate or expression tree, but don't quote me on that) and the compiler in this situation is unable to infer which was meant.
I recommend looking at the Action<T> and Func<TResult> delegates and their overloads. You can do something like this
static void Main(string[] args)
{
SomeMethod();
}
private static void SomeMethod()
{
Action<int> action = (num) => Console.WriteLine(num);
Enumerable.Range(1,10).ToList().ForEach(action);
Console.ReadKey();
}
Here SomeMethod is private and has a local Action<int> delgate that takes an int and does something to it.
I think the issue that you came across is that you can't use implicit typing (i.e. use var) when assigning a lambda expression to a variable.
You can't use the var keyword with lambdas or delegates because they both require additional context information (delegates require a return type, and lambdas require a return type and parameter types). For instance, the (params) => { code } syntax requires to be able to infer the parameter types and return types to work: you do this by explicitly giving it a type.
The generic System.Action delegate type (returns void) could do a good job at what you're trying:
Action<ArgumentType1, ArgumentType2, ...> myDelegate = (params) => { code };
Otherwise, there's also the System.Func, which has a return type, that must be passed as the last generic argument.
It depends on what your definition of hiding is.
The func/action solution (like the one Scott suggests)
void DoSomething()
{
Func<int,int> addOne = (ii) => ii +1;
var two = addOne(1);
}
Feals like hidding the method definition when writing regular C# code BUT is when looking at the IL equivalent of
//This is pseudo code but comes close at the important parts
public class Class1
{
//The actual type is different from this
private static Func<int, int> myMethod = AnonymousFunction;
public void f()
{
myMethod(0);
}
private static int AnonymousFunction(int i)
{
return 1;
}
}
So if you really want to get to the method from outside of the one "hidding" it you can do this with reflection The actual name generated for the field storing the delegate is illegal in C# bul valid in CLR context but that's the only thing that stand in the way of using the delegate as a regular delegate stored in a field (that is if you figue out the name :) )
It's quite simple actually. As the Method seems to have another responsibility than your current Class (why else would you hide this method) move your method into it's own Class and the part you want to have private into a private method in the new class.
I have a function that wraps a call to one of my socket types. If there is an error, I want to be able to print a warning and retry. In the warning, I want to have the method name. However, it was declared as a lambda. Is this even possible?
How I call the function (assume in function called myMain):
SafeSocketCommand(() => this.mySocket.ReadCurrentBuffer());
Basic wrapping function:
protected TResult SafeSocketCommand<TResult>(Func<TResult> socketCommand)
{
TResult retValue = default(TResult);
try
{
retValue = socketCommand();
}
catch (PacketLost)
{
ReportToLogs("Timeout on command '" + socketCommand.Method.Name);
}
return retValue;
}
But socketCommand.Method.Name gives me the calling method (from the Stack Trace?) '< myMain >b__3' and I want the actual function being invoked by socketCommand (mySocket.ReadCurrentBuffer). Is it possible to get this information anywhere, or is it lost due to declaring in a lambda?
EDIT:
I should have mentioned that I use this particular calling convention so that I can use socket based commands of various signatures.
int i = SafeSocketCommand(() => this.mySocket.FunctionReturnsInt())
bool b = SafeSocketCommand(() => this.mySocket.FunctionReturnsBool(string s))
object o = SafeSocketCommand(() => this.mySocket.Complicated(string s, int i, bool b))
It also handles no return type signatures by overloading:
protected void SafeSocketCommand(Action socketCommand)
{
SafeSocketCommand(() => { socketCommand(); return 0; });
}
If you modify your SafeSocketCommand to accept an Expression<Func<TResult>> then you'll get access to an expression tree that represents the body of the lambda, from which you can access the ReadCurrentBuffer call directly.
However, if you do this, you're no longer dealing with a regular anonymous method; to actually call it you'll need to compile the expression tree to code. You may also need to be flexible as to what your code expects to appear inside the lambda's body.
No, because lambda's don't have names; they're anonymous functions. You could get the method name from the last stackframe, though:
new StackFrame(1).GetMethod().Name;
Func<TResult> is just a delegate. Rather than use a lambda, create a method that matches the signature of Func<TResult> and call that. That way, you'll have whatever name you want.
SafeSocketCommand(MyNewMethod);
...
public TResult MyNewMethod()
{
return this.mySocket.ReadCurrentBuffer();
}
In this case, you can simply this call instead. It'll be faster and smaller generated code too.
SafeSocketCommand(mySocket.ReadCurrentBuffer);
In general, the StackTrace of the Exception object contains the full information you are looking for, much more accurately than printing the method name, or you can use the TargetSite property for the name of the method that threw the exception.