c# dynamic as delegate parameter - c#

Heyo,
i'm currently working on a school assignment and we should use delegate's.
So I got a delegate:
public delegate AVLNode Insert(AVLNode node, dynamic key);
And I got two different Insert Methods, the one takes a node and a string and the other one should take a node and a float as a paramter.
The problem I face now is that the delegate doesn't accept these method's because they don't match.
How can I fix tis issue without declaring the string and the int parameter as a dynamic? Sorry if my problem isn't described well, first time describing any coding problem.
Like I already said, I want a delegate with a dynamic as the parameter while both methods which will be used with the delegate have either a string or a int as the parameter.

Out of curiosity, why do you want a dynamic parameter for your key over an object which is also accepting of every type? You can then use pattern matching to ensure they are either a float or a string since you can't overload delegates. Making something dynamic also involves a lot of type checking during runtime. Why a delegate for an insert method? Do you want users to write their own insert method into a collection I assume is managed by a class? That makes no guarantee the insert delegate will insert successfully.
Generally, you mostly see delegates being used as guaranteed signatures that fulfill an operation that the user defines. For example: TimerCallback being a delegate for what happens every time a timer ticks, SpanAction<T, TArg> for letting users work with a given span and state object, custom events letting users create their own operations when something occurs, etc.
Anyways, wherever you're using your delegate, you want to make sure it is either a string or a float/int (you used both float and int seemingly interchangeably in your description). You can use this example to check for both types:
public static void Main()
{
var dyn = func(); // Returns dynamic, unknown type
if (dyn is string s)
Console.WriteLine($"string: {s}");
else if (dyn is int i)
Console.WriteLine($"int: {i}");
else if (dyn is float f) Console.WriteLine($"float: {f}");
}
Or you can use regular if statements:
public static void Main()
{
var dyn = func(); // Returns dynamic, unknown type
switch (dyn)
{
case string s:
Console.WriteLine($"string: {s}");
break;
case int i:
Console.WriteLine($"int: {i}");
break;
case float f:
Console.WriteLine($"float: {f}");
break;
}
}
But seriously, I cannot stress this enough: everything you want can very likely just be done with the object type!!! While both object and dynamic types allow for any object, dynamic allows for even specified derived types to be reassigned to any other type! For example:
public static void Main()
{
var dyn = GetDynamicInt(); // dynamic int
var n = GetInt(); // not dynamic int
dyn = Random.Shared.NextDouble(); // Now it's not an int but do you know that? Will you know that?
n = Random.Shared.NextDouble(); // Guaranteed type, this throws
}

Related

Test a function for void return in C#

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.
}
}

How to abstract operation from unrelated types?

REMARK after rethinking my issue.
Though the best solution for my exact example with WriteData method was proposed by #Dogu Arslan, the issue in question's title was actually solved by #InBetween and #Fabio. I. e. for my exact example with WriteData method it is better to move the conversion logic out of WriteData method, but to abstract the logic from unrelated types it is better to use proposed overloading. So all the three answers are helpful for me.
I already have read the following similar questions - 1, 2, and others - but not have come with something suitable solution in my case.
My case is: I have the following simple method. The important part is the line with commentary and the "source" parameter. The rest part is not so important and serves only to show that there is an "operation" from the question's title.
void WriteData(
int count,
int currentIndex,
List<byte> source,
StreamWriter sw,
string fileName)
{
var countToWrite = count - currentIndex;
if (countToWrite == 0)
return;
if (sw == null)
sw = new StreamWriter(GetFullPath(fileName));
//---------- Source's elements must be converted to string.
var dataToWrite =
source.GetRange(currentIndex, countToWrite)
.Select(x => Convert.ToString(x));
StringBuilder sb = new StringBuilder();
foreach (var item in dataToWrite)
sb.AppendLine(item);
sw.Write(sb.ToString());
}
For now I want the "source" parameter to be list with bytes, or doubles, or strings. Have I write three copies of WriteData method with only single change - the type of list in "source"? Or there is a better approach?
I tried type constraint, but to what type to constrain?
I tried to check the type and to throw exceptions if it is not in my type list (byte, double, string). But exceptions work only at run-time, and I want it to work in compile-time.
For now I have to restrict myself with run-time type checking as temporary solution, but, as I mentioned before, it is not suitable in perspective.
Why not using overload methods with one "hided" actual solution
public void WriteData(List<byte> source) { WriteData<byte>(source); }
public void WriteData(List<double> source) { WriteData<double>(source); }
public void WriteData(List<string> source) { WriteData<string>(source); }
private void WriteData<T>(List<T> source)
{
// Your actual implementation
}
In private method you can check types and throw exception when wrong type is given, in case you want "protect" from making private method public by "mistake".
The best solution is to publicly expose the needed overloads and then delegate implementation to a private generic method:
public void WriteData( , , List<string> source, , ) { WriteData<string>(...); }
public void WriteData( , , List<byte> source, , ) { WriteData<byte>(...); }
public void WriteData( , , List<double> source, , ) { WriteData<double>(...); }
private void WriteData<T>( , , List<T> source, , )
{
Debug.Assert(typeof(T).Equals(typeof(string)) ||
typeof(T).Equals(typeof(byte)) ||
typeof(T).Equals(typeof(double)));
...
}
One thing you could do is to remove the string conversion responsibility to another class altogether.ie. StringConverter class which would have overloaded constructors that would take these different input types to convert them to string and provide a method that returns a string. That way even if you extend in future the types you support you would not need to change this method here in your example, all of that would be transparent behind you string converter class. The checks will also be compile time because string converter class would take the input through its constructor. Yes this would mean everytime you want to call WriteData method you would need to instantiate a new StringConverter object but C# does not provide type constraints on the level you ask out of the shelf.

How can I set the value of a parameter that is not passed by reference in an Action<string, int>?

I have a list of Action<object, object> and I end up getting this back into an Action<string, int> at some point, or any other two types. It represents a dynamic referential mapping from one type to another. For various reasons, I cannot use ref or Func<..>.
Basically the issue is that inside the callback code for that Action<string, int> I need a way to set the value of the int that is passed in, say after I convert it from a string. Though since it is not ref, it's not obvious how to do it.
Does anyone happen to know if there is a way to rewrite the method dynamically or otherwise get at the value that is passed into it (up the stack perhaps) and set the int value... one step up the CLR call stack?
To head off anyone saying "Why not change your whole program" or "When would you ever need this?", I am simply experimenting with the idea of a new kind of object mapping library.
Interesting question, I would very much like to know the root answer!
So far, my best approach is to create your own delegate, and wrap them in generic
delegate void MyAction<T,T1>(ref T a, T1 b);
static void Main(string[] args)
{
MyAction<string, int> action = Foo;
var arr = new object[] { "", 5 };
action.DynamicInvoke(arr);
}
private static void Foo(ref string a, int b)
{
a = b.ToString();
}
Not possible with value types. They are always copied on the stack and in case of boxing (for every boxing that is encountered) they are moved to a new location in heap and a reference is passed back.
You can try and wrap your int into a reference type and take advantage of side effects (since this is exactly what you are trying to do. Or you can keep the int parameter and store the result on a closed variable. E.g.: (string str, int i) => { myDictionary.Add(str, i); }.

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(); ;
}
}

Questions on delegate functions in C#?

I'm learning about C# and one of the areas that interested me were delegate functions. The following code uses them to apply a function to each number in a range [start, limit[ before it is summed. This is a fairly simple example for clarity.
// function passing a delegate function
public override void solveProblem() {
int squareOfSum = (int) Math.Pow(Library.Math.sumRange(1, 101), 2);
int sumOfSquares = Library.Math.sumRange(1, 101, new Func<double, double, double>(Math.Pow), 2);
this.solution = (squareOfSum - sumOfSquares).ToString();
}
// function that accepts / uses delegate function
static public int sumRange(int start, int limit, Delegate operation, params object[] args) {
int sum = 0;
for (int current = start; current < limit; current++) {
// add the current number in the range as an arguement
object[] newArgs = new object[args.Length + 1];
newArgs[0] = current;
args.CopyTo(newArgs, 1);
// sum the result of the operation (delegate function)
sum += Convert.ToInt32(operation.DynamicInvoke(newArgs));
}
return sum;
}
The specific questions I have are:
Is it possible to use dynamic delegate functions (that accept a variable length list of parameters with unkown types) but force the delegate function to return a specific type? With non-dynamic delegate functions you set a return type, but also have to set the number of parameters and their types.
How much slower is using DynamicInvoke than using a non-dynamic delegate function?
What is the best way to handle parameters than what I currently do (which is accept a list of other parameters and prepend any parameters the function that uses the delegate needs to add in)?
Do I need to declare 'new Func(Math.Pow)' to pass in the power function, or is there a way to just pass Math.Pow (and have the return type and parameters be passed implicitly)?
I've looked at the C# docs and this StackOverflow question to learn how to use delegate functions, I just want to learn more about them.
Thanks!
jtfairbank
Is it possible to use dynamic delegate functions (that accept a
variable length list of parameters with unkown types) but force the
delegate function to return a specific type? With non-dynamic delegate
functions you set a return type, but also have to set the number of
parameters and their types.
You don't "force" the function to return something. The function returns something or it doesn't return something. The function "forces" you to accept something :-) (or to ignore it)
You can call a dynamic delegate through the DynamicInvoke and then cast the return value to what you know your delegate returns (or you keep it as an object). I say "what you know your delegate returns" but the reality is a little more complex: for Value Types you have to cast the return value to precisely the type used as return value or you'll get InvalidCastException. For reference types you can use an interface or a base class of the object returned (with some exceptions for Nullable types)
How much slower is using DynamicInvoke than using a non-dynamic delegate function?
I've tested a void Do() method (the most simple method possible, with no boxing for parameters) and the time difference was demential. Let's say 400x :-) On http://ideone.com/f34cj it's between 70x and 150x.
Do I need to declare 'new Func(Math.Pow)' to pass in the power function, or is there a way to just pass Math.Pow (and have the return type and parameters be passed implicitly)?
Creating a new Func/Action delegate is the right path.
In general the right solution is not what you are doing. The right solution is do as LINQ does. For example:
int pow = 2;
Func<int, int> myFunc = p => (int)Math.Pow(p, pow);
var listOfNumbers = Enumerable.Range(1, 100);
var result = listOfNumbers.Sum(p => myFunc(p));
Now, you have a delegate (myFunc) that takes a number and returns the square of that number (and note that through "closures" it closes around pow) (if you don't know what a closure is, try putting that word in google with the words lambda function). A list of numbers as an IEnumerable<int> and you do the sum of these numbers "converted" by myFunc.
Read on LINQ - usage of IEnumerable produces much more compact code.
I.e. combination of Enumrable.Range ( http://msdn.microsoft.com/en-us/library/system.linq.enumerable.range.aspx ) and Enumerable.Aggregate ( http://msdn.microsoft.com/en-us/library/bb548651.aspx ) is exactly what you trying to achieve:
var sum = Enumerable.Range(start,limit).Aggregate((s, cur)=> s+cur);
var sumSq = Enumerable.Range(start,limit).Aggregate((s, cur)=> s+ cur * cur);

Categories

Resources