473,416 Members | 1,488 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,416 software developers and data experts.

Generic Delegate Types explained (example)

Here is a good example that shows generic delegate types. Read this
through and you'll have an excellent understanding of how to use these
types. You might say that the combination of the generic delegate
type expression in just the right place and a well-named method means
we can almost read the code out loud and understand it without even
thinking.

Note that since 'boxing' and 'unboxing' is involved (I think), you
don't get what you expect if you pass a value type (see the output
labeled "//not what you want - baad!")

To get around this problem, you have to create a delegate parameter
that accepts an object (reference type). Then it works.

However, just to show how 'ref' works, when the generic method called
passes by reference rather than by object (required whenever 'new' is
used in a method) the delegate had to be renamed (from Transformer to
'Uransformer'). Don't know why this is the case but that's the way it
is.

Finally, note how you can change an object whether your pass by value
or by reference, if you are passing the object. This holds even for
strings. Note the strings are changed in both versions of the generic
delegates, "Transform2" and "Transform3".

What to make of 'generic delegate types'? After going through this
example carefully (which was a modification of a extremely primitive
example of generic delegate types taken from p. 108 of the C# 3.0
Nutshell, which formed the first output, involving squaring a value
type), I am convinced generic delegate types are a receipe for
disaster, since essentially they do away with strong typing (whatever
that means, but I have an understanding in my mind's eye).

The only advantage I can see is just a slick way of declaring a
delegate " public delegate T Transformer<T(T arg); " that will then
allow you to write methods/functions that obey this template of taking
a type T and returning a type T (whether the T is an int, a double, or
even an object), though the methods/functions are radically
different. These methods can then be called using the convention
below. Big deal. A receipe for disaster.

Big deal and a receipe for disaster is not unlike "lambda expressions"
and "anonymous delegates" (both topics I'm not that familiar with).
If anybody can relate how generic delegate types correlate with these
two topics it would be appreciated.

RL

(c) 2008, all rights reserved, by 'artistic license' and void where
prohibited. For skolarly use only. The moral rights of the author are
preserved, whatever that means. Copyleft and free to use without
attribution.

// output

1X! 2X! 3X! 1Sq! 4Sq! 9Sq! 1Cb! 64Cb! 729Cb! //note this works as
expected, since 9x9x9 = 729, and each array element is being changed
as expected.

value now [X]: 2 //not what you want - baad!
value now [Square]: 2 //not what you want - baad!
value now [Cube]: 2 //not what you want - baad!
____________

value now [X]: 3 //not what you want - baad!
value now [Square]: 3 //not what you want - baad!
value now [Cube]: 3 //not what you want - baad!
_____UtilSquarer______

value now [UtilSquarer]: 9 //now works fine
value of string [UtilSquarer]: goodbye!
_____UtilStringChanger______

value of string [UtilStringChanger]: BAA_is_a_goodBuy! //string
changed properly (1 of 2 ways to change string; see below for ref
version)
__UtilStringChanger2AndMoreStaticVer__

values of string, int are [UtilStringChanger2AndMoreStaticVersion]:
anotherStrin
gHere! , 10001
Press any key to continue . . .
/////////////////////

using System;
using System.Collections.Generic;
using System.Text;

namespace p108DelegatesCSNutshell
{
public delegate T Transformer<T(T arg);
public delegate T Uransformer<T(ref T arg); //slight name change
needed for 'ref' version, otherwise won't compile
class Program
{
static void Main(string[] args)
{
int[] values = new int[] { 1, 2, 3 };
int value = 2;
Util myUtil = new Util();

Util.Transform1(values, ReturnX); //dynamically hook
ReturnX
foreach (int i in values)
{
Console.Write(i + "X! ");
}

Util.Transform1(values, Square); //dynamically hook square
foreach (int i in values)
{
Console.Write(i + "Sq! ");
}

Util.Transform1(values, myUtil.Cube); //dynamically hook
cube
foreach (int i in values)
{
Console.Write(i + "Cb! ");
}

Console.WriteLine("\n");
myUtil.Transform2(value, ReturnX);
Console.WriteLine("value now [X]: {0}", value);
myUtil.Transform2(value, Square);
Console.WriteLine("value now [Square]: {0}", value);
myUtil.Transform2(value, myUtil.Cube);
Console.WriteLine("value now [Cube]: {0}", value);

Console.WriteLine("____________ \n");

myUtil.Transform2(myUtil.j, ReturnX);
Console.WriteLine("value now [X]: {0}", myUtil.j);
myUtil.Transform2(myUtil.j, Square);
Console.WriteLine("value now [Square]: {0}", myUtil.j);
myUtil.Transform2(value, myUtil.Cube);
Console.WriteLine("value now [Cube]: {0}", myUtil.j);

Console.WriteLine("_____UtilSquarer______ \n");

myUtil.Transform2(myUtil, myUtil.UtilSquarer);
Console.WriteLine("value now [UtilSquarer]: {0}",
myUtil.j);
Console.WriteLine("value of string [UtilSquarer]: {0}",
myUtil.s);

Console.WriteLine("_____UtilStringChanger______ \n");

myUtil.Transform3(ref myUtil, myUtil.UtilStringChanger);
Console.WriteLine("value of string [UtilStringChanger]:
{0}", myUtil.s);

Console.WriteLine("__UtilStringChanger2AndMoreStat icVer__
\n");
myUtil.Transform3(ref myUtil,
UtilStringChanger2AndMoreStaticVersion);
Console.WriteLine("values of string, int are
[UtilStringChanger2AndMoreStaticVersion]: {0} , {1}", myUtil.s,
myUtil.j);
}

static int ReturnX(int x)
{
return x;
}

static int Square(int x)
{
return x * x;
}

static Util UtilStringChanger2AndMoreStaticVersion(ref Util U)
{
U = new Util();
U.s = "anotherStringHere!";
U.j = 10001;
return U;
}

}
}
/////////////////////

using System;
using System.Collections.Generic;
using System.Text;

namespace p108DelegatesCSNutshell
{
class Util
{
public int j;
public string s;
public Util ()
{
s = "hi";
j = 3;
}

public static void Transform1<T>(T[] values, Transformer<Tt)
{
for (int i = 0; i < values.Length; i++)
values[i] = t(values[i]);
}
public int Cube(int x) { return x * x * x; }

public Util UtilSquarer(Util U)
{
U.j = U.j * U.j;
U.s = "goodbye!";

//U = new Util(); //next 3 lines won't work here since ref
not passed
//U.j = U.j * U.j;
//U.s = "NoGo";

return U;

}

public Util UtilStringChanger(ref Util U)
{
U = new Util();
U.s = "BAA_is_a_goodBuy!";
return U;
}
public void Transform2<T>(T value, Transformer<Tt)
{ value = t(value); }

public void Transform3<T>(ref T value, Uransformer<Tt)
{
value = t(ref value);
}

}
}
Aug 16 '08 #1
26 3578
raylopez99 wrote:
I am convinced generic delegate types are a receipe for
disaster, since essentially they do away with strong typing (whatever
that means, but I have an understanding in my mind's eye).
I assert that this post indicates that you have no idea what "strong
typing" means. If you do, in fact, know what strong typing means, you
should be able to convince me by showing me the type violation.

Go on. Show me.

-- Barry

--
http://barrkel.blogspot.com/
Aug 16 '08 #2
Seiously, this just isn't the right forum for this type of post. Try
something like codeproject or a blog. But to disect it:

Not only is your post full of errors both of fact and omission (and
unclear at best), you repeatedly remark that you don't understand
certain things, but somehow feel qualified to comment on them at the
same time. This post simply isn't helpful to anyone - although no
doubt another long but ultimately fruitless chain will follow. Come
on, please stop with the trolling / flamebaiting so we can actually
keep this forum useful.

Marc
Aug 16 '08 #3
raylopez99 wrote:
Here is a good example that shows generic delegate types. Read this
through and you'll have an excellent understanding of how to use these
types.
Not really, as they are not used in a way that makes sense.
You might say that the combination of the generic delegate
type expression in just the right place and a well-named method means
we can almost read the code out loud and understand it without even
thinking.

Note that since 'boxing' and 'unboxing' is involved (I think),
No, that's not correct. There is no boxing going on, unless of course
you specify "object" as the generic type, and send a value type to the
method.
you
don't get what you expect if you pass a value type (see the output
labeled "//not what you want - baad!")
If that's not what you expect, you don't really understand how arguments
are sent to a method.

You are passing a copy of the value. Changing the copy will not change
the original. That works the same way every time you call a method, it's
nothing that is special when using generics or when using delegates.
To get around this problem, you have to create a delegate parameter
that accepts an object (reference type). Then it works.
No, that doesn't make any difference.

Unless you have specifically stated that the generic type has to be a
value type, it can always be a reference type.

However, a reference is still sent by value, meaning that it's a copy of
the reference that is sent to the method. Changing the copy of the
reference still doesn't change the original reference, so you can't
replace the object even if you are sending a reference type to the method.
However, just to show how 'ref' works, when the generic method called
passes by reference rather than by object (required whenever 'new' is
used in a method)
Passing an argument by reference is not the same thing as passing a
reference type as an argument.
the delegate had to be renamed (from Transformer to
'Uransformer'). Don't know why this is the case but that's the way it
is.
That's because you can't have two methods with the same signature. The
ref keyword is not part of the signature (at least not in this context).
Finally, note how you can change an object whether your pass by value
or by reference, if you are passing the object.
No, that is not correct. You may be able to change the contents of an
object, but you can't replace the object itself if you don't send it by
reference.
This holds even for
strings. Note the strings are changed in both versions of the generic
delegates, "Transform2" and "Transform3".
No, that is not correct. Strings are immutable, meaning that you can't
change the contents of an existing string object. To change the value of
a string you have to replace it with a new string instance, which you
can not do unless you send the string by reference to the method.
What to make of 'generic delegate types'? After going through this
example carefully (which was a modification of a extremely primitive
example of generic delegate types taken from p. 108 of the C# 3.0
Nutshell, which formed the first output, involving squaring a value
type), I am convinced generic delegate types are a receipe for
disaster, since essentially they do away with strong typing (whatever
that means, but I have an understanding in my mind's eye).
No, that is not correct. Generic delegate types are still strongly
typed. Just because the type is not specified in the method doesn't mean
that it's not strongly typed. The type still has to be known at compile
time.
The only advantage I can see is just a slick way of declaring a
delegate " public delegate T Transformer<T(T arg); " that will then
allow you to write methods/functions that obey this template of taking
a type T and returning a type T (whether the T is an int, a double, or
even an object), though the methods/functions are radically
different. These methods can then be called using the convention
below. Big deal. A receipe for disaster.
The real advantage is actually not the methods that you can call using
the delegate, but the methods that you can write that calls the delegate.
Big deal and a receipe for disaster is not unlike "lambda expressions"
and "anonymous delegates" (both topics I'm not that familiar with).
If anybody can relate how generic delegate types correlate with these
two topics it would be appreciated.
Lambda expressions is just syntactic sugar for anonymous methods.

The term "anonymous delegates" doesn't really mean anything. It's like
talking about literal values as "anonymous variables". The term is
anonymous methods, and as an anonymous method doesn't have a name, the
only way to use it is by referencing it with a delegate.

An anonymous method is simply a way to write a method inlined in the
code, which then (for example) can be assigned to a delegate. Example:

// assigning a named method to a delegate:
Transformer<inttrans1 = ReturnX;
// assigning an anonymous method to a delegate:
Transformer<inttrans2 = delegate(int x) { return x; };
>
RL

(c) 2008, all rights reserved, by 'artistic license' and void where
prohibited. For skolarly use only. The moral rights of the author are
preserved, whatever that means. Copyleft and free to use without
attribution.

// output

1X! 2X! 3X! 1Sq! 4Sq! 9Sq! 1Cb! 64Cb! 729Cb! //note this works as
expected, since 9x9x9 = 729, and each array element is being changed
as expected.

value now [X]: 2 //not what you want - baad!
value now [Square]: 2 //not what you want - baad!
value now [Cube]: 2 //not what you want - baad!
____________

value now [X]: 3 //not what you want - baad!
value now [Square]: 3 //not what you want - baad!
value now [Cube]: 3 //not what you want - baad!
_____UtilSquarer______

value now [UtilSquarer]: 9 //now works fine
value of string [UtilSquarer]: goodbye!
_____UtilStringChanger______

value of string [UtilStringChanger]: BAA_is_a_goodBuy! //string
changed properly (1 of 2 ways to change string; see below for ref
version)
__UtilStringChanger2AndMoreStaticVer__

values of string, int are [UtilStringChanger2AndMoreStaticVersion]:
anotherStrin
gHere! , 10001
Press any key to continue . . .
/////////////////////

using System;
using System.Collections.Generic;
using System.Text;

namespace p108DelegatesCSNutshell
{
public delegate T Transformer<T(T arg);
public delegate T Uransformer<T(ref T arg); //slight name change
needed for 'ref' version, otherwise won't compile
class Program
{
static void Main(string[] args)
{
int[] values = new int[] { 1, 2, 3 };
int value = 2;
Util myUtil = new Util();

Util.Transform1(values, ReturnX); //dynamically hook
ReturnX
As the method is generic, you need to specify the type when you call it:

Util.Transform1<int>(values, ReturnX);
foreach (int i in values)
{
Console.Write(i + "X! ");
}

Util.Transform1(values, Square); //dynamically hook square
foreach (int i in values)
{
Console.Write(i + "Sq! ");
}

Util.Transform1(values, myUtil.Cube); //dynamically hook
cube
The Cube method should be static (se below), so you should specify the
delegate as "Util.Cube".

As you are sending a copy of the value in the variable, the method just
changes the copy and then throws it away.
foreach (int i in values)
{
Console.Write(i + "Cb! ");
}

Console.WriteLine("\n");
myUtil.Transform2(value, ReturnX);
Also a generic method, so you have to specify the type. The Transform2
method should be static (se below), so you should use the class name to
call it:

Util.Transform2<int>(value, ReturnX);

As you are sending a copy of the value in the variable, the method just
changes the copy and then throws it away.
Console.WriteLine("value now [X]: {0}", value);
myUtil.Transform2(value, Square);
Console.WriteLine("value now [Square]: {0}", value);
myUtil.Transform2(value, myUtil.Cube);
Console.WriteLine("value now [Cube]: {0}", value);

Console.WriteLine("____________ \n");

myUtil.Transform2(myUtil.j, ReturnX);
Sending a copy of a member of an object is the same as sending a copy of
a local variable. The method can still only change the copy.
Console.WriteLine("value now [X]: {0}", myUtil.j);
myUtil.Transform2(myUtil.j, Square);
Console.WriteLine("value now [Square]: {0}", myUtil.j);
myUtil.Transform2(value, myUtil.Cube);
Console.WriteLine("value now [Cube]: {0}", myUtil.j);

Console.WriteLine("_____UtilSquarer______ \n");

myUtil.Transform2(myUtil, myUtil.UtilSquarer);
Console.WriteLine("value now [UtilSquarer]: {0}",
myUtil.j);
Console.WriteLine("value of string [UtilSquarer]: {0}",
myUtil.s);

Console.WriteLine("_____UtilStringChanger______ \n");

myUtil.Transform3(ref myUtil, myUtil.UtilStringChanger);
Console.WriteLine("value of string [UtilStringChanger]:
{0}", myUtil.s);
The Transform3 method should be static (se below), so you should specify
the class name instead of an instance name.

As the method is generic, you have to specify the type when calling it.

The UtilStringChanger should be static (se below), so you should specify
the class name instead of an instance name.
>
Console.WriteLine("__UtilStringChanger2AndMoreStat icVer__
\n");
myUtil.Transform3(ref myUtil,
UtilStringChanger2AndMoreStaticVersion);
Console.WriteLine("values of string, int are
[UtilStringChanger2AndMoreStaticVersion]: {0} , {1}", myUtil.s,
myUtil.j);
}

static int ReturnX(int x)
{
return x;
}

static int Square(int x)
{
return x * x;
}

static Util UtilStringChanger2AndMoreStaticVersion(ref Util U)
{
U = new Util();
As you are immediately throwing away anything that was in the argument,
you should use "out" instead of "ref".
U.s = "anotherStringHere!";
U.j = 10001;
return U;
It's pointless to both change the argument and return it.
}

}
}
/////////////////////

using System;
using System.Collections.Generic;
using System.Text;

namespace p108DelegatesCSNutshell
{
class Util
{
public int j;
public string s;
public Util ()
{
s = "hi";
j = 3;
}

public static void Transform1<T>(T[] values, Transformer<Tt)
{
for (int i = 0; i < values.Length; i++)
values[i] = t(values[i]);
}
public int Cube(int x) { return x * x * x; }
The Cube method doesn't use anything in the Util instance, so it should
be static.
public Util UtilSquarer(Util U)
{
U.j = U.j * U.j;
U.s = "goodbye!";

//U = new Util(); //next 3 lines won't work here since ref
not passed
//U.j = U.j * U.j;
//U.s = "NoGo";

return U;
It's pointless to both change the argument and return it.
>
}

public Util UtilStringChanger(ref Util U)
The UtilStringChanger method doesn't use anything in the Util instance,
so it should be static.
{
U = new Util();
U.s = "BAA_is_a_goodBuy!";
return U;
It's pointless to both change the argument and return it.
}
public void Transform2<T>(T value, Transformer<Tt)
The Transform2 method doesn't use anything in the Util instance, so it
should be static.
{ value = t(value); }
Assigning the return value from the delegate call to the value variable
doesn't serve any purpose. As the argument only contains a copy of the
value (regardless if the value is a value type value or a reference to a
reference type) it's never used after the assignment.
>
public void Transform3<T>(ref T value, Uransformer<Tt)
The Transform3 method doesn't use anything in the Util instance, so it
should be static.
{
value = t(ref value);
It's pointless to both send the value variable by reference to the
delegate call and assigning the return value to it. Whatever the method
assigns to the argument, it will be overwritten by the return value.
}

}
}

--
Göran Andersson
_____
http://www.guffa.com
Aug 17 '08 #4
"raylopez99" <ra********@yahoo.comwrote:
generic delegate types [...] essentially [...] do away with strong typing
But they don't at all. Having a type parameter does not weaken the method
signature. The compiler still won't let you do anything you couldn't do with
a particular specified type in a non-generic delegate.

Eq.
Aug 17 '08 #5
raylopez99 wrote:
Here is a good example that shows generic delegate types.
Only half of that sentence is correct.

Don't draw conclusions if you already know you don't have all the facts. Ask
questions instead. Conclusions don't teach. Attempting to explain things to
an audience may help raise questions, but leave it at that.

--
J.
Aug 17 '08 #6

Sorry but my reply got truncated.

In a nutshell, I made the point that the string was changed from "hi"
to "goodbye" using value passing, then to "BAA _is_a_Good_Buy" using
reference passing, and the fact that the string in the first case was
not technically mutated or changed (because 'new' was not used) is
semantics. You may be correct about the semantics, but from a user's
point of view the important thing is that the string contents were
changed. And the program does show you how to change / mutate the
actual string reference / memory location using 'ref' and 'new'.
>
No, that is not correct. Generic delegate types are still strongly
typed. Just because the type is not specified in the method doesn't mean
that it's not strongly typed. The type still has to be known at compile
time.
HAHAHA! You fell for a trap. In fact, there is no generally agreed
definition of strongly typed. Wikipedia it.

The real advantage is actually not the methods that you can call using
the delegate, but the methods that you can write that calls the delegate.
Semantics. That's what I meant.

Lambda expressions is just syntactic sugar for anonymous methods.

The term "anonymous delegates" doesn't really mean anything. It's like
talking about literal values as "anonymous variables". The term is
anonymous methods, and as an anonymous method doesn't have a name, the
only way to use it is by referencing it with a delegate.
OK, I'll keep this in mind. I have a printout of some Lambda
expressions that I have to study.
>
An anonymous method is simply a way to write a method inlined in the
code, which then (for example) can be assigned to a delegate. Example:

// assigning a named method to a delegate:
Transformer<inttrans1 = ReturnX;
// assigning an anonymous method to a delegate:
Transformer<inttrans2 = delegate(int x) { return x; };
I see. THank you. THis was helpful. Now I get it. It's inline
code.

RL
Aug 17 '08 #7
On Aug 16, 5:28*pm, Jeroen Mostert <jmost...@xs4all.nlwrote:
raylopez99 wrote:
Here is a good example that shows generic delegate types.

Only half of that sentence is correct.

Don't draw conclusions if you already know you don't have all the facts. Ask
questions instead. Conclusions don't teach. Attempting to explain things to
an audience may help raise questions, but leave it at that.
What is your question? Or do you just like making accusations?

RL

Aug 17 '08 #8
On Aug 16, 3:41*pm, Barry Kelly <barry.j.ke...@gmail.comwrote:
raylopez99 wrote:
I am convinced generic delegate types are a receipe for
disaster, since essentially they do away with strong typing (whatever
that means, but I have an understanding in my mind's eye).

I assert that this post indicates that you have no idea what "strong
typing" means. If you do, in fact, know what strong typing means, you
should be able to convince me by showing me the type violation.

Go on. Show me.

-- Barry

--http://barrkel.blogspot.com/
Wikipedia claims there's no generally agreed definition of 'strong
typing', last I checked.

So it was a trick question.

BTW, for the rest of you too lazy to read my code--one interesting
thing I found was this:

public void Transform2<T>(T value, Transformer<Tt)
{ value = t(value); }

if "T" is a primitive data type (non-object, like int), the generic
delegate Transform2 will not work. But if it's an object, it will, as
I demonstrated in my OP.

Beats me why.

RL
Aug 17 '08 #9
raylopez99 <ra********@yahoo.comwrote:
On Aug 16, 3:41*pm, Barry Kelly <barry.j.ke...@gmail.comwrote:
raylopez99 wrote:
I am convinced generic delegate types are a receipe for
disaster, since essentially they do away with strong typing (whatever
that means, but I have an understanding in my mind's eye).
I assert that this post indicates that you have no idea what "strong
typing" means. If you do, in fact, know what strong typing means, you
should be able to convince me by showing me the type violation.

Go on. Show me.
Wikipedia claims there's no generally agreed definition of 'strong
typing', last I checked.
Certainly, but to claim that generic delegates do away with strong
typing is simply wrong by *any* widely used definition of strong
typing.
So it was a trick question.
Not really. While there are various understandings, none of them are
compatible with your claim that generic delegates "do away with strong
typing". Once again your "mind's eye" seems to be highly flawed. I'd
stop trusting it, if I were you...
BTW, for the rest of you too lazy to read my code--one interesting
thing I found was this:

public void Transform2<T>(T value, Transformer<Tt)
{ value = t(value); }

if "T" is a primitive data type (non-object, like int), the generic
delegate Transform2 will not work. But if it's an object, it will, as
I demonstrated in my OP.
Um, it will work perfectly well actually.

Admittedly changing the value of a parameter (effectively a local
variable) and then ignoring the new value is somewhat odd, but it will
still operate perfectly well.

Of course, it depends on what you expect it to do. If you could post a
short but complete program (one which only tries to demonstrate *one*
thing) which doesn't work as you expect it to, we can explain your
misunderstanding.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Aug 17 '08 #10
raylopez99 wrote:
Sorry but my reply got truncated.

In a nutshell, I made the point that the string was changed from "hi"
to "goodbye" using value passing,
No, you didn't. You only showed that you can change the members of an
object that you pass as argument.
then to "BAA _is_a_Good_Buy" using
reference passing,
As you are changing the members of the object and not the object itself,
passing the object by reference has no relevance.
and the fact that the string in the first case was
not technically mutated or changed (because 'new' was not used) is
semantics. You may be correct about the semantics, but from a user's
point of view the important thing is that the string contents were
changed. And the program does show you how to change / mutate the
actual string reference / memory location using 'ref' and 'new'.
No, the program doesn't show that.
>No, that is not correct. Generic delegate types are still strongly
typed. Just because the type is not specified in the method doesn't mean
that it's not strongly typed. The type still has to be known at compile
time.

HAHAHA! You fell for a trap. In fact, there is no generally agreed
definition of strongly typed. Wikipedia it.
HAHAHA! You fell for a trap. ;) That doesn't matter. However you define
type strength, generic delegates doesn't make the code weakly typed.
>The real advantage is actually not the methods that you can call using
the delegate, but the methods that you can write that calls the delegate.

Semantics. That's what I meant.

>Lambda expressions is just syntactic sugar for anonymous methods.

The term "anonymous delegates" doesn't really mean anything. It's like
talking about literal values as "anonymous variables". The term is
anonymous methods, and as an anonymous method doesn't have a name, the
only way to use it is by referencing it with a delegate.

OK, I'll keep this in mind. I have a printout of some Lambda
expressions that I have to study.
>An anonymous method is simply a way to write a method inlined in the
code, which then (for example) can be assigned to a delegate. Example:

// assigning a named method to a delegate:
Transformer<inttrans1 = ReturnX;
// assigning an anonymous method to a delegate:
Transformer<inttrans2 = delegate(int x) { return x; };

I see. THank you. THis was helpful. Now I get it. It's inline
code.

RL

--
Göran Andersson
_____
http://www.guffa.com
Aug 17 '08 #11
raylopez99 wrote:
BTW, for the rest of you too lazy to read my code--one interesting
thing I found was this:

public void Transform2<T>(T value, Transformer<Tt)
{ value = t(value); }

if "T" is a primitive data type (non-object, like int), the generic
delegate Transform2 will not work. But if it's an object, it will, as
I demonstrated in my OP.

Beats me why.

RL
No, it doesn't work properly either with value types or reference types.
As I explained in my other post, assigning the return value from the
delegate call to the value argument has no effect at all, as the
argument value is a copy and will never be used any more.

If the generic type is a reference type, the delegate method can change
the members of the object, but it can not change the object itself.
Also, if the class is immutable like for example the String class, the
delegate method can't change any members of the object, so it will not
be able to change anything at all.

--
Göran Andersson
_____
http://www.guffa.com
Aug 17 '08 #12
raylopez99 wrote:
On Aug 16, 3:41*pm, Barry Kelly <barry.j.ke...@gmail.comwrote:
raylopez99 wrote:
I am convinced generic delegate types are a receipe for
disaster, since essentially they do away with strong typing (whatever
that means, but I have an understanding in my mind's eye).
I assert that this post indicates that you have no idea what "strong
typing" means. If you do, in fact, know what strong typing means, you
should be able to convince me by showing me the type violation.

Go on. Show me.
Wikipedia claims there's no generally agreed definition of 'strong
typing', last I checked.
Assuming Wikipedia had a monopoly on the truth, then how can you claim a
type violation, if such a thing is undefined?

Or on the other hand, perhaps there is some set of definitions of
"strong typing" - which I disagree with, BTW, I think the term is well
defined for any given type system, and with the CLR we do indeed have a
type system - but even if so, you should be able to choose *one* of
them, and show the type violation.

I'm still waiting.

-- Barry

--
http://barrkel.blogspot.com/
Aug 17 '08 #13
raylopez99 wrote:
On Aug 16, 5:28 pm, Jeroen Mostert <jmost...@xs4all.nlwrote:
>raylopez99 wrote:
>>Here is a good example that shows generic delegate types.
Only half of that sentence is correct.

Don't draw conclusions if you already know you don't have all the facts. Ask
questions instead. Conclusions don't teach. Attempting to explain things to
an audience may help raise questions, but leave it at that.

What is your question? Or do you just like making accusations?
It's advice.

--
J.
Aug 17 '08 #14
On Aug 17, 10:26*am, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
>
BTW, for the rest of you too lazy to read my code--one interesting
thing I found was this:
* * * * public void Transform2<T>(T value, Transformer<Tt)
* * * * { value = t(value); }
if "T" is a primitive data type (non-object, like int), the generic
delegate Transform2 will not work. But if it's an object, it will, as
I demonstrated in my OP.

Um, it will work perfectly well actually.

Admittedly changing the value of a parameter (effectively a local
variable) and then ignoring the new value is somewhat odd, but it will
still operate perfectly well.

Of course, it depends on what you expect it to do. If you could post a
short but complete program (one which only tries to demonstrate *one*
thing) which doesn't work as you expect it to, we can explain your
misunderstanding.
I did post complete code. COpy and paste it. I omitted nothing.

Why didn't squaring the number work in these code fragments?

//
value = t(value);

public int Cube(int x) { return x * x * x; }

myUtil.Transform2(value, myUtil.Cube);
Console.WriteLine("value now [Cube]: {0}", value);
//

Only when I changed it to this (an object) did it work properly:

//
public Util UtilSquarer(Util U)

{
U.j = U.j * U.j;
//

RL
Aug 18 '08 #15
On Aug 17, 10:59*am, Göran Andersson <gu...@guffa.comwrote:
raylopez99 wrote:
In a nutshell, I made the point that the string was changed from "hi"
to "goodbye" using value passing,

No, you didn't. You only showed that you can change the members of an
object that you pass as argument.
And for practical programming that's nearly the only thing that
matters. You're still stuck in semantics Goran. Again, the rule of
thumb is this: if you use 'new', then pass by reference using 'ref' to
change the object; if not, you can still change the object by passing
by value in C#.

Nuff said.

RL

Aug 18 '08 #16
On Aug 17, 12:36*pm, Göran Andersson <gu...@guffa.comwrote:
raylopez99 wrote:
BTW, for the rest of you too lazy to read my code--one interesting
thing I found was this:
* * * * public void Transform2<T>(T value, Transformer<Tt)
* * * * { value = t(value); }
if "T" is a primitive data type (non-object, like int), the generic
delegate Transform2 will not work. But if it's an object, it will, as
I demonstrated in my OP.
Beats me why.
RL

No, it doesn't work properly either with value types or reference types.
As I explained in my other post, assigning the return value from the
delegate call to the value argument has no effect at all, as the
argument value is a copy and will never be used any more.
Then show us how it can work other than my solution, which I
demonstrated. Quite playing semantic games like Jon likes to do. It
doesn't make you, a programmer, look more scientific in front of the
hard sciences like engineering and physics. It just makes you look
like a trivial pedant.
RL
Aug 18 '08 #17
Why didn't squaring the number work in these code fragments?

Because Transform2 is defined as:

public void Transform2<T>(T value, Transformer<Tt)
{ value = t(value); }

And you never retreive the "value" arg. The most sensible fix would be
to have Transform2 "return value;" at the end; then I suspect you'll
find that:

value = myUtil.Transform2(value, myUtil.Cube);

will update value. Or treat value as a ref argument.

Marc
Aug 18 '08 #18
I have answered this (with example) on your other e-mail. But these are
not semantic games nor is it pedantry - they are essential terms that
you have clearly not understood fully, but which you *need* to learn if
you are going to understand what is going on here.

Marc
Aug 18 '08 #19
On Aug 18, 10:09*am, raylopez99 <raylope...@yahoo.comwrote:
Of course, it depends on what you expect it to do. If you could post a
short but complete program (one which only tries to demonstrate *one*
thing) which doesn't work as you expect it to, we can explain your
misunderstanding.

I did post complete code. COpy and paste it. *I omitted nothing.
But you were trying to show too much in one program. That's why I
asked you for a short but complete program which only tries to
demonstrate *one* thing. That way it's a lot easier to talk about.
Why didn't squaring the number work in these code fragments?
Because you *still* appear not to understand parameter passing.
See http://pobox.com/~skeet/csharp/complete.html

Hint: this has nothing to do with delegates. Do the same thing with
normal method calls and you'll see the same result.

Jon
Aug 18 '08 #20
You're still stuck in semantics Goran. Again, the rule of
thumb is this: if you use 'new', then pass by reference using 'ref' to
change the object; if not, you can still change the object by passing
by value in C#.
You can keep saying this, but you are still wrong. It has nothing to do
with "new", and everything to do with changing the value of the
parameter and expecting the caller to see the change.

The important bit here is "value of the parameter", not "properties of
the object that the reference points to". For reference-types (classes)
the value of the parameter is just (essentially) a number; in pointer
terms it would be the address of the remote object (references work
slightly differently, but can be considered in that way).

You keep changing the object that the reference points to, but this is
not what "ref" means.

Marc
Aug 18 '08 #21
On Aug 18, 10:38*am, "Jon Skeet [C# MVP]" <sk...@pobox.comwrote:
Because you *still* appear not to understand parameter passing.
See http://pobox.com/~skeet/csharp/complete.html
Sorry, wrong link:
http://pobox.com/~skeet/csharp/parameters.html

Jon
Aug 18 '08 #22
raylopez99 wrote:
On Aug 17, 10:59 am, Göran Andersson <gu...@guffa.comwrote:
>raylopez99 wrote:
>>In a nutshell, I made the point that the string was changed from "hi"
to "goodbye" using value passing,
No, you didn't. You only showed that you can change the members of an
object that you pass as argument.

And for practical programming that's nearly the only thing that
matters. You're still stuck in semantics Goran. Again, the rule of
thumb is this: if you use 'new', then pass by reference using 'ref' to
change the object; if not, you can still change the object by passing
by value in C#.

Nuff said.

RL
You are totally missing the point. You say that your example is showing
something, but it isn't. It doesn't matter whether your code works or
not, it doesn't work the way that you are saying that it is.

--
Göran Andersson
_____
http://www.guffa.com
Aug 18 '08 #23
raylopez99 wrote:
On Aug 17, 12:36 pm, Göran Andersson <gu...@guffa.comwrote:
>raylopez99 wrote:
>>BTW, for the rest of you too lazy to read my code--one interesting
thing I found was this:
public void Transform2<T>(T value, Transformer<Tt)
{ value = t(value); }
if "T" is a primitive data type (non-object, like int), the generic
delegate Transform2 will not work. But if it's an object, it will, as
I demonstrated in my OP.
Beats me why.
RL
No, it doesn't work properly either with value types or reference types.
As I explained in my other post, assigning the return value from the
delegate call to the value argument has no effect at all, as the
argument value is a copy and will never be used any more.

Then show us how it can work other than my solution, which I
demonstrated.
I did. Read my reply to your OP, where I have pointed out in detail most
of the mistakes in your code.

--
Göran Andersson
_____
http://www.guffa.com
Aug 18 '08 #24
On Aug 18, 2:28*am, Marc Gravell <marc.grav...@gmail.comwrote:
Why didn't squaring the number work in these code fragments?

Because Transform2 is defined as:

* * * * *public void Transform2<T>(T value, Transformer<Tt)
* * * * *{ value = t(value); }

And you never retreive the "value" arg. The most sensible fix would be
to have Transform2 "return value;" at the end; then I suspect you'll
find that:

* *value = myUtil.Transform2(value, myUtil.Cube);

will update value. Or treat value as a ref argument.

Marc
Thanks Marc--your suggestion worked. Just made the changes now, and
it's interesting. The ref argument 'fix' I've already done in my
original post; this below code is using a return value.

There are two keys to making this example work with non-classes (ints,
doubles, etc): you need to fix the 'transform' (generic delegate
template or whatever) to have a return type when dealing with value
types, and, importantly, you need to assign the return to a Left Hand
Side.

RL

int NewInt = 69;

myUtil.Transform2Marc(NewInt, Square);

Console.WriteLine("value now [69 squared? no!]: {0}", NewInt);

//note, you must assign the RHS to a LHS for this to work, hence the
penultimate line above fails.
//no! 69 not squared to 69^2! does not work

int NewIntAnotherVariable; // key! to have a LHS (left hand side)

NewIntAnotherVariable = myUtil.Transform2Marc(NewInt, Square); //try
this, different? Yes!

Console.WriteLine("value now [69 squared? Yes!]: {0}",
NewIntAnotherVariable);

//works! gives 4761, which is 69*69.
///////// THis is the fix, adding one line as suggested by Marc

public T Transform2Marc<T>(T value, Transformer<Tt)
{
value = t(value);
return value; //ADD THIS LINE: important change allows
'primitive' data types to be assigned values (compare to objects)
}

///as an aside, and nothing to do with this post, this below code does
not work as generic--I believe because C# does not support, like in C+
+ making generics of functions, but only making generics of class
types, but I'm not sure

// static T cuber (<T>)
//{
// return T*T*T*T;

//}

// cuber fails to compile. You need to preface T with 'int' or
'double' or a class name for cuber to compile.

What an excellent learning exercise this is/was for anybody reading
this thread. This is the best of Usenet.

RL
Aug 18 '08 #25
raylopez99 wrote:
On Aug 18, 2:28 am, Marc Gravell <marc.grav...@gmail.comwrote:
>>Why didn't squaring the number work in these code fragments?
Because Transform2 is defined as:

public void Transform2<T>(T value, Transformer<Tt)
{ value = t(value); }

And you never retreive the "value" arg. The most sensible fix would be
to have Transform2 "return value;" at the end; then I suspect you'll
find that:

value = myUtil.Transform2(value, myUtil.Cube);

will update value. Or treat value as a ref argument.

Marc

Thanks Marc--your suggestion worked. Just made the changes now, and
it's interesting. The ref argument 'fix' I've already done in my
original post; this below code is using a return value.

There are two keys to making this example work with non-classes (ints,
doubles, etc): you need to fix the 'transform' (generic delegate
template or whatever) to have a return type when dealing with value
types, and, importantly, you need to assign the return to a Left Hand
Side.

RL
Was that really what you were looking for? Why didn't you ask for that
in the first place, instead of writing a highly confused article trying
to explain something that you don't understand?

I've seen many different ways in how people fail to ask a proper
question, but this has to be the strangest by far...

--
Göran Andersson
_____
http://www.guffa.com
Aug 18 '08 #26
On Aug 18, 10:50*am, Göran Andersson <gu...@guffa.comwrote:
Was that really what you were looking for? Why didn't you ask for that
in the first place, instead of writing a highly confused article trying
to explain something that you don't understand?
Because it was not apparent until after the fact.

RL
Aug 18 '08 #27

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

Similar topics

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...
3
by: Aquila Deus | last post by:
Hi all! I found a problem when using generic with delegate: delegate RT MethodTemplate <RT> (); delegate RT MethodTemplate <RT, AT0> (AT0 a0); delegate RT...
3
by: markww | last post by:
Hi, I have a wrapper around some 3rd party database library function. The pseudo code looks like the following - it is meant to open a table in a database, extract values from a table, then copy...
6
by: Jorge Varas | last post by:
Hi all, Is it possible to have a collection of a generic type? for example: class a<twhere t : class, new { }
7
by: Ido Samuelson | last post by:
Hello, What do you think about the following features: public class GenericDecorator<T: T { } can leverage to a few things:
7
by: Dave | last post by:
I've got these declarations: public delegate void FormDisplayResultsDelegate<Type>(Type displayResultsValue); public FormDisplayResultsDelegate<stringdisplayMsgDelegate; instantiation:...
0
by: Peter Duniho | last post by:
On Thu, 26 Jun 2008 00:05:42 -0700, <zorrothefox.groups@gmail.comwrote: Yes, it is "klunky". IMHO, it's unfortunate that that's the model MSDN continues to suggest everywhere. If you are...
7
by: raylopez99 | last post by:
On Aug 16, 3:49 pm, Marc Gravell <marc.grav...@gmail.comwrote: If you cannot understand such a simple post, then you don't understand generic delegate types. Apparently you can only read your...
8
by: Advait Mohan Raut | last post by:
Hello, I am using VC# 2005 ; C# 2.0 I am working on the performance measurement tool. For that I need my code to call user defined method along with its parameters. For that should I use a...
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: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
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,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

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.