473,396 Members | 1,938 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Generics with List and Delegates?

I wasn't sure if I could do this. I believe I am stretching the capability of
what generics can do for me but here goes.

I have a generic delegate defined as
public delegate bool RuleDelegate<T>(T item);

In my class my goal is to use a generic list collection to contain my
generic delegates. This will allow me to pass this List to another library
and call this list of functions. This could provide a new way to build rule
base engines in .NET if this is possible thus being independant of
implementation. Is this possible with .NET 2.0?
--
Cedric Rogers
What buy when you can tradeforit
at http://www.trademeforit.com
Jun 27 '06 #1
4 2785
"Cedric Rogers" <ce**********@trademeforit.com> a écrit dans le message de
news: 91**********************************@microsoft.com...

|I wasn't sure if I could do this. I believe I am stretching the capability
of
| what generics can do for me but here goes.
|
| I have a generic delegate defined as
| public delegate bool RuleDelegate<T>(T item);
|
| In my class my goal is to use a generic list collection to contain my
| generic delegates. This will allow me to pass this List to another
library
| and call this list of functions. This could provide a new way to build
rule
| base engines in .NET if this is possible thus being independant of
| implementation. Is this possible with .NET 2.0?

As far as I have been able to ascertain, it is not possible to have a list
of generic delegates, they would have to be bound to one particular type.

However, I would be grateful to find that I am wrong, because it is
something that I had hoped to do.

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Jun 27 '06 #2
Cedric Rogers <ce**********@trademeforit.com> wrote:
I wasn't sure if I could do this. I believe I am stretching the capability of
what generics can do for me but here goes.

I have a generic delegate defined as
public delegate bool RuleDelegate<T>(T item);

In my class my goal is to use a generic list collection to contain my
generic delegates. This will allow me to pass this List to another library
and call this list of functions. This could provide a new way to build rule
base engines in .NET if this is possible thus being independant of
implementation. Is this possible with .NET 2.0?


I'm not sure exactly what you're asking for. Why isn't:

List<RuleDelegate<int>> intRuleList = // ...

good enough?

Is it that you want all the delegates in the list to have the same
signature? In that case, why isn't:

delegate object DynamicInvokeMethod(params object[] args);
List<DynamicInvokeMethod> rules = new List<DynamicInvokeMethod>();
rules.Add(myIntDelegate.DynamicInvoke);
rules.Add(myFooDelegate.DynamicInvoke);

good enough?

Is it that you want pattern matching on the basis of the type of the
argument? In that case, why not write a class which uses the above
DynamicInvoke along with perhaps a dictionary mapping the type of the
argument to the corresponding delegates?

Generics are a tool for static typing - they may do dynamic work at
*compile* time, but everything must be statically resolved before the
compilation ends. If you're trying to get dynamic typing behaviour,
generics aren't a sufficient tool. However, with the ability in .net to
reflect over the generic parameters of any particular instantiation,
they can still be useful in dynamic situations.

-- Barry

--
http://barrkel.blogspot.com/
Jun 27 '06 #3
"Barry Kelly" <ba***********@gmail.com> a écrit dans le message de news:
u7********************************@4ax.com...

| I'm not sure exactly what you're asking for. Why isn't:
|
| List<RuleDelegate<int>> intRuleList = // ...
|
| good enough?

Because I think Cedric wants a list of RuleDelegate<T> (unbound).

| Is it that you want all the delegates in the list to have the same
| signature? In that case, why isn't:
|
| delegate object DynamicInvokeMethod(params object[] args);
| List<DynamicInvokeMethod> rules = new List<DynamicInvokeMethod>();
| rules.Add(myIntDelegate.DynamicInvoke);
| rules.Add(myFooDelegate.DynamicInvoke);
|
| good enough?

I can't quite work out what you are doing here, this also seems to need a
bound delegate type to work. I do understand that generics are not meant to
allow dynamlic typing, but I also have come against a problem when I need to
use a non-generic method to link a generic event to a generic handler.

| Is it that you want pattern matching on the basis of the type of the
| argument? In that case, why not write a class which uses the above
| DynamicInvoke along with perhaps a dictionary mapping the type of the
| argument to the corresponding delegates?

Hmmm, this looks interesting, I will have to investigate this. Have you
actually used this technique, or is it pure untested inspiration ? :-)

| Generics are a tool for static typing - they may do dynamic work at
| *compile* time, but everything must be statically resolved before the
| compilation ends. If you're trying to get dynamic typing behaviour,
| generics aren't a sufficient tool. However, with the ability in .net to
| reflect over the generic parameters of any particular instantiation,
| they can still be useful in dynamic situations.

I feel that generics were introduced, in part, to resolve the speed penalty
of having to use reflection, so I am loathe to have to use reflection to
resolve generics issues.

If I want a list of a generic *type*, then I will create a non-generic base
class and derive the generic class from it. This then allows me to hold a
list of the non-generic base type, regardless of the bound parameter.

However, I *think* that there are occasions when I want to have a list of
unbouond delegates and would want to use the same "base non-generic
delegate" technique, which is not possible.

Could I trouble you to elucidate further on your DynamicInvokeMethod idea ?

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Jun 28 '06 #4
"Joanna Carter [TeamB]" <jo****@not.for.spam> wrote:
"Barry Kelly" <ba***********@gmail.com> a écrit dans le message de news:
u7********************************@4ax.com...

| I'm not sure exactly what you're asking for. Why isn't:
|
| List<RuleDelegate<int>> intRuleList = // ...
|
| good enough?

Because I think Cedric wants a list of RuleDelegate<T> (unbound).
How would you use such a type? You couldn't call it, because you can't
provide values of type 'T' (the Invoke method on the delegate isn't
itself generic). You couldn't add anything to it, because it's
impossible to create object instances of type 'RuleDelegate<T>' (the
method table entry for the Invoke method would need to point to a method
that manipulates a fictional type - T).

Can you write the code that adds to the list, and calls items in the
list? From what I can see, you might be after pattern matching in the
functional style, as seen in languages like Haskell.

The problem is, if you've got two delegates in there, one taking int and
the other taking string, and now you want to call the delegates and
you've got (say) a string value, what bits succeed due to static type
checking? What bits fail?
| Is it that you want all the delegates in the list to have the same
| signature? In that case, why isn't:
|
| delegate object DynamicInvokeMethod(params object[] args);
| List<DynamicInvokeMethod> rules = new List<DynamicInvokeMethod>();
| rules.Add(myIntDelegate.DynamicInvoke);
| rules.Add(myFooDelegate.DynamicInvoke);
|
| good enough?

I can't quite work out what you are doing here, this also seems to need a
bound delegate type to work.
What could you possibly do with an instance of an open generic type? Can
you write some (pseudo)code showing how to use an instance of an open
generic type?
I do understand that generics are not meant to
allow dynamlic typing, but I also have come against a problem when I need to
use a non-generic method to link a generic event to a generic handler.
Can you say more about what a "generic event" is? Or do you mean a
generic delegate, say something like:

void Foo<T>(T value) { Console.WriteLine(value); }

// ...

Action<T> action = Foo;

.... such that whenever you call action(x), it instantiates the correct
Foo<typeof(x)> and invokes it?

This is effectively trying to imperatively create an alias for an
existing generic method. For this to work, the Invoke() method on
Action<T> would need to be generic itself, and when it is instantiated,
it would need to instantiate the right Foo<T> and invoke it.

A problem with that is that the assignment or delegate combine is
imperative, so for any given Action<T>, the compiler couldn't reliably
know what Foo<T> (and/or Bar<T> etc.) it is attached to, due to the
halting problem. Thus, when generating code for our mythical
Action<T>.Invoke<T>(T value) (Invoke would need to become generic), it
couldn't produce code which actually instantiates a Foo<T> or a Bar<T>.
Instead, it would need to use reflection to look up the open generic
methods it is bound to, and fill in the generic arguments for each one
of them, and finally invoke each of them.

A big point of generics is that it can lead to performance improvements
due to elimination of reflection or other dynamic typing techniques. So,
in order to avoid doing that work each time, it would need to cache the
values somewhere. It can't be directly in fields, because that would
cause the physical object size to grow dynamically. Thus it would have
to store a dictionary mapping the types of the arguments to the
instances of Foo<>/Bar<> etc.

I think at this point the compiler is producing a bunch of code that
isn't a whole lot better than what you or I could write ourselves using
Reflection and Reflection.Emit.

To be clear, this thing I'm talking about here is something different
from the thing I've appended to the document. The thing here needs a
generic Invoke<> method, while the thing I've appended takes in a
"params object[]".
| Is it that you want pattern matching on the basis of the type of the
| argument? In that case, why not write a class which uses the above
| DynamicInvoke along with perhaps a dictionary mapping the type of the
| argument to the corresponding delegates?

Hmmm, this looks interesting, I will have to investigate this. Have you
actually used this technique, or is it pure untested inspiration ? :-)
It was sourced from functional programming. I have used Reflection.Emit
to avoid reflection overhead when dynamically binding to a method, but
it was a slightly different scenario.
| Generics are a tool for static typing - they may do dynamic work at
| *compile* time, but everything must be statically resolved before the
| compilation ends. If you're trying to get dynamic typing behaviour,
| generics aren't a sufficient tool. However, with the ability in .net to
| reflect over the generic parameters of any particular instantiation,
| they can still be useful in dynamic situations.

I feel that generics were introduced, in part, to resolve the speed penalty
of having to use reflection, so I am loathe to have to use reflection to
resolve generics issues.

If I want a list of a generic *type*, then I will create a non-generic base
class and derive the generic class from it. This then allows me to hold a
list of the non-generic base type, regardless of the bound parameter.

However, I *think* that there are occasions when I want to have a list of
unbouond delegates and would want to use the same "base non-generic
delegate" technique, which is not possible.

Could I trouble you to elucidate further on your DynamicInvokeMethod idea ?


The pattern-matching based on the types of the arguments is tricky,
because you've got to consider derived types etc. For example, if you
have two methods:

Foo(string, object)

and

Foo(object, string)

both added to the delegate, and you then try to call:

foo(null, null)

which one should it call? All possible ones? Exact matches?

The approach I've taken below is to call all possible matches. The code
isn't totally error-checked, YMMV. Hacked up in a few minutes, etc. :)

---8<---
using System;
using System.Collections.Generic;
using System.Reflection;

class DynamicDelegate
{
private List<DelegatePattern> _patterns =
new List<DelegatePattern>();

public DynamicDelegate()
{
}

public void Add(Delegate d)
{
if (d == null)
throw new ArgumentNullException("d");

int index = IndexOf(d.GetType());
DelegatePattern pattern;
if (index != -1)
pattern = _patterns[index];
else
{
pattern = new DelegatePattern(d.GetType());
_patterns.Add(pattern);
}

pattern.Target = Delegate.Combine(pattern.Target, d);
}

public void Remove(Delegate d)
{
if (d == null)
throw new ArgumentNullException("d");

int index = IndexOf(d.GetType());
if (index == -1)
return;

DelegatePattern pattern = _patterns[index];
pattern.Target = Delegate.Remove(pattern.Target, d);
if (pattern.Target == null)
_patterns.RemoveAt(index);
}

private int IndexOf(Type delegateType)
{
return _patterns.FindIndex(delegate(DelegatePattern item)
{
return object.Equals(item.DelegateType, delegateType);
});
}

public object Invoke(params object[] arguments)
{
// Convert "Invoke(null)" to "Invoke(new object[] { null })".
if (arguments == null)
arguments = new object[] { null };

object result = null;
foreach (DelegatePattern pattern in _patterns)
if (pattern.IsMatch(arguments))
result = pattern.Target.DynamicInvoke(arguments);
return result;
}

class DelegatePattern
{
private Type[] _types;
private Type _delegateType;
private Delegate _target;

public DelegatePattern(Type delegateType)
{
_types =
Array.ConvertAll<ParameterInfo,Type>(
delegateType.GetMethod("Invoke").GetParameters(),
delegate(ParameterInfo p)
{ return p.ParameterType; });
}

public bool IsMatch(object[] arguments)
{
if (arguments.Length != _types.Length)
return false;
for (int i = 0; i < arguments.Length; ++i)
if (!IsAssignableTo(arguments[i], _types[i]))
return false;
return true;
}

private bool IsAssignableTo(object source, Type target)
{
if (source == null)
{
if (target.IsGenericType
&& target.GetGenericTypeDefinition() ==
typeof(Nullable<>))
return true;
return !target.IsValueType;
}
return target.IsInstanceOfType(source);
}

public Delegate Target
{
get { return _target; }
set { _target = value; }
}

public Type DelegateType
{
get { return _delegateType; }
set { _delegateType = value; }
}
}
}

class App
{
static void Main()
{
DynamicDelegate d = new DynamicDelegate();
d.Add(new Action<string>(Write));
d.Add((Action<int>) delegate(int x)
{ Console.WriteLine("An int: {0}", x); });
d.Add((Action<object>) delegate(object o)
{ Console.WriteLine("An object: {0}", o); });
d.Add(new Action<int?>(Write));

d.Invoke("some string");
d.Invoke(42);
d.Invoke(null);
}

static void Write<T>(T value)
{
Console.WriteLine("A '{0}': {1}", typeof(T).Name, value);
}
}
--->8---

-- Barry

--
http://barrkel.blogspot.com/
Jun 28 '06 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: andrew queisser | last post by:
I've read some material on the upcoming Generics for C#. I've seen two types of syntax used for constraints: - direct specification of the interface in the angle brackets - where clauses I...
17
by: Andreas Huber | last post by:
What follows is a discussion of my experience with .NET generics & the ..NET framework (as implemented in the Visual Studio 2005 Beta 1), which leads to questions as to why certain things are the...
16
by: bigtexan | last post by:
I would like to do the following and cannot figure it out. public class A<T> { public delegate T GetValueDelegate(A<T> var); public GetValueDelegate GetValue = new GetValueDelegate(B.GetValue);...
12
by: Michael S | last post by:
Why do people spend so much time writing complex generic types? for fun? to learn? for use? I think of generics like I do about operator overloading. Great to have as a language-feature, as...
9
by: sloan | last post by:
I'm not the sharpest knife in the drawer, but not a dummy either. I'm looking for a good book which goes over Generics in great detail. and to have as a reference book on my shelf. Personal...
4
by: Bill Woodruff | last post by:
< note : this message was sparked in part by comments by David Browne on a previous thread : "inserting an anonymous method as a value in a generic dictionary ?" : David had shown the use of...
3
by: rbjorkquist | last post by:
I am looking for some help figuring out the best way to refactor these two examples. I was thinking of using delegates and/or generics; but have little experience with either. Any sample code...
1
by: Bruce Wood | last post by:
I'm trying to "genericize" the following class. At the moment I have derived classes for each different type of event handler / event arguments, and I wanted to have a single, generic, catch-all...
8
by: Tony Johansson | last post by:
Hello! I have read that in practice, casting proved to be several times faster than using a generic. So the main reason to use generics is not that the performance is better because that's...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.