Re: Structs and delegates
- From: "Abubakar" <abubakarm@xxxxxxxxx>
- Date: Wed, 5 Oct 2005 12:58:18 -0700
Hi,
if I compile your code under Rotor csc, it gives me the following error:
---------------------------------------
Unhandled Exception: System.NotSupportedException: Delegates on value
classes can only be formed on virtual methods
at System.Delegate.NeverCallThis(Object target, IntPtr slot)
at ConsoleApplication1.Class1.Main(String[] args)
---------------------------------------
Ab.
http://joehacker.blogspot.com
"Michi Henning" <michi@xxxxxxxxx> wrote in message
news:OU%23%23mRVyFHA.2644@xxxxxxxxxxxxxxxxxxxxxxx
> Below is a bit of code that creates a delegate.
> The delegate invokes a member function of a struct.
> The code compiles, but has surprising behavior:
>
> using System;
>
> namespace ConsoleApplication1
> {
> public struct SimpleStruct
> {
> public int i;
>
> public void assignToI(int x)
> {
> Console.WriteLine("Assigning i: " + x);
> i = x;
> Console.WriteLine("i = " + x);
> }
> }
>
> class Class1
> {
> public delegate void Assigner(int s);
>
> private static void callDelegate(Assigner a, int i)
> {
> a(i);
> }
>
> static void Main(string[] args)
> {
> SimpleStruct s = new SimpleStruct();
> s.assignToI(1); // Works as expected, assigns 1 to s.i
> System.Console.WriteLine("s.i after calling assignToI = " +
s.i);
>
> // Create a delegate that calls assignToI()
> Assigner assign_to_i = new Assigner(s.assignToI);
>
> // Call helper function, passing delegate and new value for
s.i
> callDelegate(assign_to_i, 99);
>
> System.Console.WriteLine("s.i after calling delegate = " +
s.i);
> // Assignment is lost, s.i still contains 1!!!
> }
> }
> }
>
> When run, this code prints:
>
> $ ./ConsoleApplication1.exe
> Assigning i: 1
> i = 1
> s.i after calling assignToI = 1
> Assigning i: 99
> i = 99
> s.i after calling delegate = 1
>
> Note that the direct call s.assignToI() works as expected:
> after the call, the structure member has new value.
>
> However, the call via the delagate does not work as expected:
> the value that is assigned is lost, and the structure member
> has the old value.
>
> Now, I realize what is going on here. The delegate constructor
> expects an argument of type object. In other words, the expression
>
> new Assigner(s.assignToI)
>
> is internally converted to something like
>
> new Delegate(s, "assignToI")
>
> So, the struct is silently boxed and, when the delegate runs,
> what it assigns to is a temporary copy of the struct on the heap,
> instead of assigning to the real struct.
>
> Several thoughts here:
>
> 1) I find this surprising. At no point in my code have I passed the
> structure as a parameter, so I don't expect this behavior. (Yes,
> I know that the struct ends up being boxed, but that is not manifest
> anywhere in the code.)
>
> 2) I believe that the behavior is wrong. (Yes, I understand *why* it
> works the way it does, but that doesn't necessarily make the behavior
> right.) Delegates are the equivalent of C++ member function pointers.
> If I create a delegate and pass a method of a struct, I expect the
> delegate to call the method on the struct instance I specified, not
> some temporary copy.
>
> 3) Even if we accept that the behavior is correct, then why does the
compiler
> allow me to write this? After all, there is no way that such a
delegate would
> ever do something useful, so why not at least emit a warning?
>
> 4) The silent boxing and unboxing in C# seems to be more of a curse than
helpful.
> It is too easy to have a value type boxed, only to end up with
invocations
> made to a boxed copy on the heap.
>
> Finally, I'm looking for suggestions as to how I can achieve what the
above
> code is trying to do. Basically, what I need to do is assign to a member
of
> an already instantiated structure, but without knowing the type of the
structure.
> That is, I want to, at least in spirit, be able to assign to a structure
member
> via a pointer to the structure.
> (This issue arises in the context of unmarshaling data from the wire and,
for
> various legitimate reasons, I have to assign to a member of an already
instatiated
> structure, instead of instantiating the structure after I have all its
member values.)
>
> I tried using pointers and unsafe code, but that only works for types that
are unmanaged.
> However, the structure may contain managed members, in which case I can no
> longer create a pointer to the struct, so this doesn't work either.
>
> Any other ideas anyone?
>
> Thanks,
>
> Michi.
.
- Follow-Ups:
- Re: Structs and delegates
- From: Abubakar
- Re: Structs and delegates
- Prev by Date: Re: XML load
- Next by Date: Re: Structs and delegates
- Previous by thread: Re: Structs and delegates
- Next by thread: Re: Structs and delegates
- Index(es):
Relevant Pages
|