Craig wrote:
Hi Frans
Thanks for the reply. I realise if I change the signature of the delegate
to match the function all would be ok.
Here's a snipet of what I want to do:
delegate void SomeDelegate(ICollection collection);
void SomeDispatch(ICollection collection) {
SomeDelegate sd = null;
if(collection is ArrayList) {
sd = new SomeDelegate(SomeMethod);
}
else if (collection is BitAray) {
sd = new SomeDelegate(SomeMethod1);
}
sd.Invoke(collection);
}
void SomeMethod(ArrayList al) {
// do something specific for an ArrayList
Console.Write(al.Count.ToString());
}
void SomeMethod1(BitArray ba) {
// do something specific to a BitArray
Console.Write(ba.Count.ToString());
}
As you need to query the specific type in your dispatch method anyway,
I would do the needed downcast right there:
namespace ConsoleApplication
{
delegate void SomeDelegateArrayList(ArrayList collection);
delegate void SomeDelegateSortedList(SortedList collection);
class Program
{
static void SomeDispatch(ICollection collection)
{
Delegate sd = new SomeDelegateArrayList(SomeMethodDefault);
if (collection is ArrayList)
{
sd = new SomeDelegateArrayList(SomeMethodArrayList);
}
else if (collection is SortedList)
{
sd = new SomeDelegateSortedList(SomeMethodSortedList);
}
sd.DynamicInvoke(collection);
}
static void SomeMethodArrayList(ArrayList al)
{
// do something
Console.Write(al.Count.ToString());
}
static void SomeMethodSortedList(SortedList sl)
{
// do something
Console.Write(sl.Count.ToString());
}
static void SomeMethodDefault(ICollection al)
{
// do sensible default??
throw new NotImplementedException();
}
static void Main(string[] args)
{
}
}
}
>
Whether I use an interface or an abstract class in the delegate signature I
fully expected the compiler to reflect the actual passed argument ensuring it
was the correct or derived from the correct type.
Do you think is a reasonable assumption?
Nope. If this would be possible you could do something like this:
namespace ConsoleApplication
{
delegate void SomeDelegate(ICollection collection);
class Program
{
static void SomeDispatch()
{
SortedList sl = new SortedList();
sl.Add("hello", "hello");
SomeDelegate sd = new SomeDelegate(SomeMethod);
sd.Invoke(sl);
}
static void SomeMethod(ArrayList al)
{
// do something
al.AddRange(new int[]{1, 2});// How would that work for a
// sorted list??
}
static void Main(string[] args)
{
}
}
}
The delegate is a contract. It says: "When you have a delegate of this
type, it can work with an ICollection."
Your function has a contract stating: "This function can handle an
ArrayList"
ArrayList is a ICollection, but you can do a lot more with it! So how
should the compiler and/or runtime handle it, especially if all these
bits are defined across different assemblies?
BTW, in classic C++ or Java you would model a delegate using an interface:
interface ISomeDelegate
{
void SomeMethod(ICollection al);
}
and what you expect would look like this:
class SomeDelegate : ISomeDelegate
{
void SomeMethod(ICollection al);
}
which wouldn't compile either.
BTW, it does work the other way round:
namespace ConsoleApplication
{
// delegate taking the specialized type
delegate void SomeDelegate(ArrayList collection);
class Program
{
static void SomeDispatch()
{
ArrayList al = new ArrayList();
al.Add("hello");
SomeDelegate sd = new SomeDelegate(SomeMethod);
sd.Invoke(al);
}
// function that takes the base type
static void SomeMethod(ICollection al)
{
// do something
Console.Write(al.Count.ToString());
}
static void Main(string[] args)
{
}
}
}
HTH,
Andy