How allow passing just "allowed" delegates as parameter of function in C# - c#

I have a bit interresting problem, i wasn't able to find solution. I have 4 different delegates and want to use junt one of them as parameter of function. But the only solution, I found is :
void doSomething(Delegate delegate){ }
but I don't want to be able pass every delegate but just one of these:
public delegate void CopyStatusDelegate(long fileSize, long copied);
public delegate void CopyProgressDelegate(int progress);
public delegate void CopyEstimatedDelegate(int copyTimeSeconds, int estimatedTimeSeconds);
public delegate void CopyAllInfoDelegate(long fileSize, long copied, int progress, int copyTimeSeconds, int estimatedTimeSeconds);
Is in c# any else solution except of throwing an Exception when input delegate isn't one of these?

Write four overloads of doSomething, each of which accepts one of these delegates. The compiler will prevent you from passing in anything else, and if you need to for some reason (it's not very clear) you can forward from these overloads to a protected or private method that accepts any delegate.

Related

How to add methods to the invocation list of a delegate without instantiating the delegate?

I have to add multiple methods to the invocation list of a delegate. However, all of them have decision logic associated with them. So, there's an if block before the method gets attached to the invocation list of the delegate. Can I do this without instantiating the delegate. The code snippet looks like the following:
public delegate void SomeDelegate();
static void Method1() {}
static void Method2() {}
static void AddMethodsToInvocationList()
{
SomeDelegate someDelegate = new SomeDelegate();
if (someLogic1) someDelegate += Method1;
if (someLogic2) someDelegate += Method2;
}
Basically, I wish to be able to create an instance of the delegate without passing any methods as parameters. However I get a compiler error with "does not contain a constructor that takes 0 arguments" error, if I try and instantiate the delegate without passing any methods as parameters.
I would also be open to solving this issue a different way if someone else has a better way of doing it. However, delegates have to be used.
Thank you for any help. Much appreciated.
You can simply initialize it to null. That is the idiomatic value for a multicast delegate that doesn't have any operations added to it.

C# How to declare lambda or anonymous function type in method argument list?

I don't know if this is possible in C#. But here's what I'm trying to do:
An interface that declares a method with a completion block / callback / lambda / whatever you want to call it. Seems simple enough. But, here's a first attempt:
namespace N {
interface MyInterface {
delegate void CompletionBlock();
void doSomething(CompletionBlock completionBlock);
}
}
But interfaces can't declare delegates. Ok, how about this?
namespace N {
public delegate void CompletionBlock();
interface MyInterface {
void doSomething(CompletionBlock completionBlock);
}
}
Sure that works, but now, say I declare another type of CompletionBlock, one which takes an argument for instance. I can't call the type CompletionBlock because it'll clash with the above type, if inside the same namespace.
Then there's Action and Func. But even Action takes a parameter, and I want no parameters. So Action doesn't seem like a viable candidate. Really, all I want, is a way of inlining the concept of "anonymous block as long as the signature is void(void). Something like this:
namespace N {
interface MyInterface {
void doSomething(typeof(()=>) completionBlock);
}
}
But lambdas don't really have a type in C#. Do they at least have signatures?
Basically, is there any way around this?
In Objective-C, for instance, blocks are of type NSBlock, even though their signatures themselves are not easily accessible, but one can create a method that takes a block with a specific signature. For instance:
- (void)doSomething:(void(^)(void))completionBlock
Would be a method that takes a block with no parameters and no return type, and you'd call the method like so, for instance:
[obj doSomething:^(){your block code}];
Then there's Action and Func. But even Action takes a parameter, and I want no parameters. So Action doesn't seem like a viable candidate.
If you use Action (not Action<T>), it does not take parameters.
namespace N {
interface MyInterface {
void doSomething(Action completionBlock);
}
}
This allows you to write:
yourInstance.doSomething(() => DoWhatever(foo));
Or, if DoWhatever is void DoWhatever(), just:
yourInstance.doSomething(DoWhatever);
Use Action<T> or Func<TResult> or one of their siblings or just Action in your case.
Action<...> don't return anything where as Func<..., TResult> do.

Best way to pass delegate parameters

What is the best way to pass parameters through to a delegate? I can see benefits for both of the following ways so I would like to know the most used and industry accepted way of doing it:
1) Pass any parameters individually with each parameters being just that, a parameter.
Example Delegate
public delegate void MyDelegate(bool PARAM1, String PARAM2, int PARAM3);
2) Pass any parameters through a struct and the only parameter of the delegate is that struct.
Example Struct
public struct MyDelegateArgs
{
public bool PARAM1;
public String PARAM2;
public int PARAM3;
}
Example Delegate
public delegate void MyDelegate(MyDelegateArgs args);
Imagine your struct had 20 properties / fields - would you really want to pass all of those in as parameters? Generally I would argue to hide all of this complexity and keep your code DRY by passing in a class / struct instead - this in most cases is also more expressive - your delegates needs a parameter of type MyDelegateArgs.
The only argument I could come up with for passing in individual values is if you only need a small subset that just happen to be used in MyDelegateArgs but are otherwise unrelated.
If your delegate has utility as an Action<T> or a Predicate<T>, using the struct argument is preferable as it will keep you from tripping over a case where the signature gets too large for the predefined Action or Predicate definitions when you go to extend the delegate's signature.

Delegate Questions

I am new to C# and have two questions about delegates.
MSDN shows that the Delegate class only has two constructors, both which take two arguments each. However, in the program below, I am instantiating a Delegate object with a seemingly one-parameter constructor (see the commented line).
using System;
static class Program
{
public delegate void MyDelegate();
static void MyMethod()
{
Console.WriteLine("I'm inside MyMethod!");
}
static void Main()
{
MyDelegate myDelegate = new MyDelegate(MyMethod); // Constructor Call
myDelegate();
}
}
Am I misunderstanding something?
My second question is: when declaring delegates with one or more parameters, why do we need to give the parameters names? In C++, we could do something like this inside classes:
public delegate void MyOtherDelegate(int, int, string);
It may look like you're calling a standard constructor, but the C# compiler is actually doing a little slight of hand with your code. When you write
MyDelegate myDelegate = new MyDelegate(MyMethod);
You're not actually invoking any of the constructors listed on MSDN directly. It instead calls a constructor that the compiler has automatically defined on the delegate type MyDelegate (these constructors are not shown on MSDN). In fact, the constructors that are listed on MSDN cannot even be called directly:
This constructor cannot be used in application code. To create a delegate by specifying the name of an instance method, use an overload of the CreateDelegate method…
It's worth noting that you can even do this for brevity:
MyDelegate myDelegate = MyMethod;
As for why parameter names are necessary, perhaps they may not be strictly necessary for compilation in general, but I suspect that the designers of the CLR wanted to be consistent with other features of the in the run-time. It allows you to do things like specifying explicit parameter names that you wouldn't be able to do otherwise:
Func<int, int> foo = x => x + 1;
foo(arg: 1);
It also means you can inspect the parameter names through reflection and potentially do some useful processing with them.
Not exactly answering your question but just so you are aware, C# also supports Func delegates. in which case you don't need to even declare anything.
e.g. This method accepts a delegate with a parameter of type string and output of Int
public static void DoSomethingWithDelegate(Func<string, Int32> converstionDelegate)
{
int x = converstionDelegate("1");
}
Read more about it here: http://msdn.microsoft.com/en-us/library/bb549151.aspx

C# function that takes pointer to function as an in parameter without declaring any specific delegate types?

I want to implement a method that will find stuff in my custom class. It should work like generic collections work - i pass a pointer to a function, and the method will iterate through all it has to look in, apply this function, and if it returns true return the found item.
I'd like to pass function pointer as a parameter, but i dont want to declare delegate types.
I know i can do something like:
delegate bool Foo(MyClass)
MyClass MyMethod(Foo x)
{...}
And i know i can do something like this:
MyClass MyMethod(Func<MyClass,bool> x)
But can i do it without declaring a delegate type and without using built in stuff like Func<> which has limits on how many parameters i can have (in case of Func, one...)
You can just use delegate if you want, although it's a bit old school :)
public void TestInvokeDelegate()
{
InvokeDelegate( new TestDelegate(ShowMessage), "hello" );
}
public void InvokeDelegate(TestDelegate del, string message)
{
del(message);
}
public delegate void TestDelegate(string message);
public void ShowMessage(string message)
{
Debug.WriteLine(message);
}
You can allways pass in a Delegate and call DynamicInvoke on it:
MyClass MyMethod(Delegate x) {
// ...
x.DynamicInvoke(....);
// ...
}
It looks like you are trying to implement the Visitor pattern. In this case visiting methods usually have only one parameter - the instance to visit. Having additional arguments passed around conceals the use of the pattern and makes it harder to reason about. This article shows you one way to implement it in C#.
The key is to create a visitor class that will encapsulate all the parameters that affect the visiting process. This way you don't need to pass anythnig other than an object in question in the visiting method - everything else lives in instance fields.
However, if you really want to pass some additional parameters in the method and don't know what type they can have, there are ways to do that. More or less standard approach in .NET world is to use a delegate without return value and with single parameter of type object, the example would be ParameterizedThreadStart delegate:
public delegate void ParameterizedThreadStart(
Object obj
)
This way you get to pass only one parameter in the delegate, but it could be anything - an instance of a class, an array or null, if you end up not needing additional arguments after all. The downside of this approach is that it requires type casting which can lead to runtime errors.

Categories