Can't pass delegate - c#

I've created a function that gets console input from the user as-long as it fits a filter so to speak.
public delegate TResult OutFunc<in T, TValue, out TResult>(T arg1, out TValue arg2);
public static T PromptForInput<T>(string prompt, OutFunc<string, T, bool> filter)
{
T value;
do { Console.Write(prompt); }
while (!filter(Console.ReadLine(), out value));
return value;
}
This works great when I call the method as I do below. which gets a number from the user as long as it parses to an int which is in the range of (0-10).
int num = PromptForInput("Please input an integer: ",
delegate(string st, out int result)
{ return int.TryParse(st, out result) && result <= 10 && result >= 0; } );
I want to be able to re-use common filters. In multiple places in my program I want to get an int input from the user, so I've separated out the logic for that, and put that in its own function.
private bool IntFilter(string st, out int result)
{
return int.TryParse(st, out result) && result <= 10 && result >= 0;
}
Now I get an error when I attempt to do this:
int num = PromptForInput("Please input an integer: ", IntFilter);
The type arguments for method 'PromptForInput(string, OutFunc)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
How can I explicitly specify the type arguments in this case?

You have a generic function, and so need to declare the type:
int num = PromptForInput<int>("Please input an integer: ", IntFilter);
The compiler is just saying it can't figure that out on it's own and needs it declared explicitly.

Thanks to LordTakkera's answer I was able to also find this works as-well
int num = PromptForInput("Please input an integer: ", new OutFunc<string, int, bool>(IntFilter));
The compiler actually does this implicitly when compiling as long as you explicitly specify PromptForInput<int>. Though, I don't understand why the compiler can't figure this out implicitly.

Related

What is the difference between Expression.Variable() and Expression.Parameter()?

Both seem to return the same type, and have the same signature.
So what is the difference between them, and when should we use each?
Expression.Variable is used to declare a local variable within a block. Expression.Parameter is used to declare a parameter for an incoming value.
Now currently C# doesn't allow statement-bodied lambda expressions, but if it did, imagine:
// Not currently valid, admittedly...
Expression<Func<int, int>> foo = x =>
{
int y = DateTime.Now.Hour;
return x + y;
};
If this were valid, the C# compiler would generate code using Expression.Parameter for x, and Expression.Variable for y.
At least, that's my understanding. It's a real shame that the documentation for the two methods is basically the same :(
Effectively, there is no difference, apart from the fact that Variable() does not allow ref types. To see that, you can look at the reference source:
public static ParameterExpression Parameter(Type type, string name) {
ContractUtils.RequiresNotNull(type, "type");
if (type == typeof(void)) {
throw Error.ArgumentCannotBeOfTypeVoid();
}
bool byref = type.IsByRef;
if (byref) {
type = type.GetElementType();
}
return ParameterExpression.Make(type, name, byref);
}
public static ParameterExpression Variable(Type type, string name) {
ContractUtils.RequiresNotNull(type, "type");
if (type == typeof(void)) throw Error.ArgumentCannotBeOfTypeVoid();
if (type.IsByRef) throw Error.TypeMustNotBeByRef();
return ParameterExpression.Make(type, name, false);
}
As you can see, both methods call ParameterExpression.Make(), so the returned object will behave the same.

Multicast Delegates must have a return type of void. Why?

Multicast Delegates must have a return type of void Otherwise it will throw an exception.
I want to know whats the reason behind it, what if multiple methods could have a same return type as of a delegate ?
The premise is wrong; it works fine:
Func<int> func = delegate { Console.WriteLine("first part"); return 5; };
func += delegate { Console.WriteLine("second part"); return 7; };
int result = func();
That is a multicast delegate with a non-void result, working fine. You can see from the console that both parts executed. The result of the last item is the one returned. We can demonstrate that this is a true multicast delegate:
if(func is MulticastDelegate) Console.WriteLine("I'm multicast");
and it will write "I'm multicast" even after just the first line (when there is only a single method listed).
If you need more control over individual results, then use GetInvocationList():
foreach (Func<int> part in func.GetInvocationList())
{
int result = part();
}
which allows you to see each individual result.
In IL terminology:
.class public auto ansi sealed Func<+ TResult>
extends System.MulticastDelegate`
which is to say: Func<T> inherits from MulticastDelegate. Basically, to all intents and purposes, all delegates in .NET are multicast delegates. You might be able to get a non-multicast delegate in managed C++, I don't know. But certainly not from C#.
The following answer is factually wrong, because you currently *can* have multicast delegates with non-void return type (the jury is still out regarding whether this has always been so). However, it does answer the question "Why might a language disallow such delegates?", so I am leaving it for completeness.
Now go and upvote Marc.
Because the multiple methods would return multiple values, so what should the one return value of the delegate be then? Clearly there is no answer that would be satisfying in all circumstances. You could argue that the multicast delegate should:
return the value of the first method in invocation order (but IIRC invocation order is unspecified, so how would this work?)
return the value of the last method, as above
return the single distinct value returned by all delegates; throw an exception if not all of them agree
in multicast the problem is that it override all values just print the last method value if it have return type,so you have to capture the return type of one by one,lets see the code below
class Program
{
// i am going to add and subtract two num but i wanna get result in string the same thing you can do for int and what ever you want
delegate string mydeledagte(int a,int b);
delegate string d(int s, int t);
static void Main(string[] args)
{
mydeledagte ab = new mydeledagte(ad);
mydeledagte d= new mydeledagte(sub);
mydeledagte multi = ab + d;
foreach (mydeledagte individualMI in multi.GetInvocationList())
{
string retVal = individualMI(3, 5);
Console.WriteLine("Output: " + retVal);
Console.WriteLine("\n***developer of KUST***");
Console.ReadKey();
}
}
static string ad(int a, int b)
{
return (a + b).ToString();
}
static string sub(int a, int b)
{
return (a - b).ToString(); ;
}
}

Using Func<T> parameters

I have a Func in my code that's declared like this:
Func<string, int, bool> Filter { get; set; }
How can I reach the string and the int variables that are parameters of the Func in order to use them in my code?
The parameters only exist when the function is called... and they're only available within the function. So for example:
foo.Filter = (text, length) => text.Length > length;
bool longer = foo.Filter("yes this is long", 5);
Here, the value "yes this is long" is the value of the text parameter while the delegate is executing and likewise the value 5 is the value of the length parameter while it's executing. At other times, it's a meaningless concept.
What are you really trying to achieve? If you could give us more context, we could almost certainly help you better.
You could use an anonymous method:
Filter = (string s, int i) => {
// use s and i here and return a boolean
};
or a standard method:
public bool Foo(string s, int i)
{
// use s and i here and return a boolean
}
and then you could assign the Filter property to this method:
Filter = Foo;
See this sample here - http://www.dotnetperls.com/func
using System;
class Program
{
static void Main()
{
//
// Create a Func instance that has one parameter and one return value.
// ... Parameter is an integer, result value is a string.
//
Func<int, string> func1 = (x) => string.Format("string = {0}", x);
//
// Func instance with two parameters and one result.
// ... Receives bool and int, returns string.
//
Func<bool, int, string> func2 = (b, x) =>
string.Format("string = {0} and {1}", b, x);
//
// Func instance that has no parameters and one result value.
//
Func<double> func3 = () => Math.PI / 2;
//
// Call the Invoke instance method on the anonymous functions.
//
Console.WriteLine(func1.Invoke(5));
Console.WriteLine(func2.Invoke(true, 10));
Console.WriteLine(func3.Invoke());
}
}

In overloading why the return type of the function is not considered? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Function overloading by return type?
Hi,
In overloading we say that the parameter list has to be different either by number or by type, but doesn't matter on the return type, Why is that so???
The function
//Function 1
int Add(int a, int b)
{return a+b;}
//Function 2
Double Add(Double a, Double b)
{return a+b;}
//Function 3
Double Add(int a, int b)
{return (Double)a+b;}
The functions 1 2 are overloaded, where as functions 1 and 3 are not ??? Reasons ???
Any help is really appreciated.
The compiler needs to know at compile time which function you are trying to call. If they differ only by return type, this is usually not possible. Consider, for example:
var result = Add(1, 2);
or
Console.WriteLine(Add(1, 2));
the compiler would not be able to know whether you want to execute function 1 or 3. And even if you did
double x = Add(1, 2);
the compiler would not know if you (a) want to call function 3 or (b) call function 1 and do an implicit widening conversion from int to double.
There are to many cases where that kind of overloading would not work. Here is two of them:
You don't care about the result of the method, and call it like this:
Add(3, 4);
Should this call method 1 or 3?
You use varto assign the result
var result = Add(3, 4);
This kind of overloading would be ambiguous at best, so therefore it's not allowed.
The other answers deal with why, but an aside: in C# you can simulate return-type based overloading by using (abusing?) implicit conversion operators (and deferring the operation):
using System;
class Program {
static void Main() {
int i = Add(3, 5); // prints: int overload called
double d = Add(3, 5); // prints: double overload called
}
static SuperMagicAdder Add(int a, int b)
{ return new SuperMagicAdder(a, b); }
}
struct SuperMagicAdder {
private readonly int a,b;
public SuperMagicAdder(int a, int b) { this.a = a; this.b = b; }
public override string ToString() { return a + "+" + b; }
public static implicit operator int (SuperMagicAdder value) {
Console.WriteLine("int overload called");
return value.a + value.b;
}
public static implicit operator double (SuperMagicAdder value) {
Console.WriteLine("double overload called");
return (double)value.a + value.b;
}
}
Note that interestingly, Anonymous Function Literals in C# are overloaded on their result type and it doesn't seem to pose any problems.
In C#, a lambda can be two very different things:
a piece of executable code (a subclass of Delegate actually)
an abstract representation of an operation (basically, an abstract syntax tree)
This is distinguished purely by the result type of the lambda literal:
Func<int, int> l = (i) => i + i * i;
is a piece of executable code. I can say
Console.WriteLine(l(3));
and I will get 12.
Expression<Func<int, int>> e = (i) => i + i * i;
is an abstract representation of that operation. I can say
Console.WriteLine(e);
and I will get
i => (i + (i * i))
Note that this is not just the original text. It really is an rendering of the abstract representation. The extra parentheses around the expression and inside it are there, because ToString() did an actual tree traversal of the AST and rendered it. The AST looks roughly like this:
And this
var v = (i) => i + i * i;
is simply illegal, because lambdas are overloaded on their result type, but the var keyword says "use the result type to figure out the type of v".
Allowing return types to be part of the signature would create major ambiguities in overload resolution.
For example, consider:
Add(2,3);
We are "throwing away" the value returned by the method, but which overload should be invoked?
It doesn't work well with implicit-typing, or with assigning the value to a variable that is compatible with either return-type. E.g.:
var sum = Add(2,3);
object sum = Add(2,3);

Scope of variables inside anonymous functions in C#

I have a doubt in scope of varibles inside anonymous functions in C#.
Consider the program below:
delegate void OtherDel(int x);
public static void Main()
{
OtherDel del2;
{
int y = 4;
del2 = delegate
{
Console.WriteLine("{0}", y);//Is y out of scope
};
}
del2();
}
My VS2008 IDE gives the following errors:
[Practice is a class inside namespace Practice]
1.error CS1643: Not all code paths return a value in anonymous method of type 'Practice.Practice.OtherDel'
2.error CS1593: Delegate 'OtherDel' does not take '0' arguments.
It is told in a book: Illustrated C# 2008(Page 373) that the int variable y is inside the scope of del2 definition.
Then why these errors.
Two problem;
you aren't passing anything into your del2() invoke, but it (OtherDel) takes an integer that you don't use - you still need to supply it, though (anonymous methods silently let you not declare the params if you don't use them - they still exist, though - your method is essentially the same as del2 = delegate(int notUsed) {...})
the delegate (OtherDel) must return an int - your method doesn't
The scoping is fine.
The error has nothing to do with scopes. Your delegate must return an integer value and take an integer value as parameter:
del2 = someInt =>
{
Console.WriteLine("{0}", y);
return 17;
};
int result = del2(5);
So your code might look like this:
delegate int OtherDel(int x);
public static void Main()
{
int y = 4;
OtherDel del = x =>
{
Console.WriteLine("{0}", x);
return x;
};
int result = del(y);
}

Categories

Resources