Re: Structs and delegates

Tech-Archive recommends: Fix windows errors by optimizing your registry



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.


.



Relevant Pages

  • Re: Structs and delegates
    ... I meant compile AND run. ... >> The delegate invokes a member function of a struct. ... >> I tried using pointers and unsafe code, but that only works for types ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Structs and delegates
    ... > The delegate invokes a member function of a struct. ... > Assigning i: 1 ... Delegates are the equivalent of C++ member function pointers. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: GPO Management Delegation
    ... Domain and Forest in native 2003 mode. ... explicitly granted the permission to link GPOs in the OU in question. ... group they are a member of has been granted that right. ... Curious, if you delegate the user directly, does it work? ...
    (microsoft.public.windows.server.active_directory)
  • Re: Unable to unlock peer group members accounts
    ... Roger, Steven, thanks both of you for your valuable input which do help us in further troubleshoot our Unlock User account issue. ... In other words, if you have peer group member users but they reside in different OUs, then make sure you delegate to each Ou respectively with the required delegated group memebership. ...
    (microsoft.public.windows.server.security)
  • Re: Unable to unlock peer group members accounts
    ... Roger, Steven, thanks both of you for your valuable input which do help us in further troubleshoot our Unlock User account issue. ... In other words, if you have peer group member users but they reside in different OUs, then make sure you delegate to each Ou respectively with the required delegated group memebership. ...
    (microsoft.public.win2000.security)