Alois Kraus

blog

  Home  |   Contact  |   Syndication    |   Login
  111 Posts | 8 Stories | 296 Comments | 162 Trackbacks

News



Article Categories

Archives

Post Categories

Image Galleries

Programming

 After reading Mike Stalls Debugging Blog I was wondering if it is really impossible to pass property values by reference:
    void PassIntByRef(ref int x)
    ...
    PassIntByRef(ref MyProperty);
  <-- this is illegal in C#.
Another restriction which is often annoying is that you cannot have property delegates.

    class PropertyDelegation

    {

        public delegate int ReturnValueDelegate();

 

        ReturnValueDelegate ValueGetter;

 

        int x = 0;

        public int X  // This is our beloved property we care so much about.

        {

            get { return x; }

            set { x = value; }

        }

 

        public PropertyDelegation()

        {

            ValueGetter = X;      // Illegal in C#

            ValueGetter = GetX;   // Legal code

        }

        int GetX()

        {

            return X;

        }

   }


The above workaround with the GetX function is not really nice but it works and I wondered if there is no other way to do this. After 10 minutes thinking about this I did realize that both problems could be solved by a reference type which provides the needed functionality.
  • The new type should provide a getter and setter for the wrapped property.
  • Expose Get and Set functions to attach delegates to it
  • Provide a as much type safety as possible.
Lets look what the C# compiler does produce for a Property with a getter and setter. Using Reflector we quickly see what really happens:
Property with Getter and Setter under the Reflector Microscope
Hm the property is in reality a set of two methods. If we get our hands on both methods we can create a delegate from it and call them by our selfs inside our wrapper class (reference type object). Extensions to compiled types at run time calls for the reflection API. In our case the PropertyInfo class provides all information we want. The result of this is my new class PropertyInvoker which fulfills all three requirements.

    public class PropertyInvoker

    {

        private PropertyInfo propInfo;

        private object obj;

 

        public PropertyInvoker(string PropertyName, object o)

        {

            obj = o;

            propInfo = o.GetType().GetProperty(PropertyName);

        }

 

        public T Property

        {

            get

            {

                return (T) propInfo.GetValue(obj, null);

            }

 

            set

            {

                propInfo.SetValue(obj, value, null);

            }

        }

 

        public T GetProperty()

        {

            return Property;

        }

 

        public void SetProperty(T value)

        {

            Property = value;

        }

    }


This little helper allows us to create a delegate function from a property:

        public delegate int ReturnValueDelegate();

        ReturnValueDelegate ValueGetter;


        // Create delegate around the get property of X

        ValueGetter = new ReturnValueDelegate(new PropertyInvoker<int>("X", this).GetProperty);

        int realval = ValueGetter.Invoke(); // Call get property with our new invoker


Properties cannot be really passed by reference but at least we did come quite close to our initial goal:

        private void Add(PropertyInvoker<int> value)

        {

            value.Property++;

        }


        // Pass property by reference inside wrapped type

        Add(new PropertyInvoker<int>("X", this));

 

Ok this looks nice but how about performance? Reflection is known to be slow after all. The good news is that on my P4 3.0 GHz PC at home I can call value.Property++ over 300 000 times/s. This is quite good for an indirect function call via reflection. The bad news is the native property is much better. To be precise about several hundred times faster. Why? I think the JITer is very good at detecting this set_X and get_X methods in my code and does simply inline the calls. Against inlined function calls my PropertyInvoker has clearly no chance since at runtime there is no method call due to god work of the JITer. To check this assumption and to prevent such an unfair "optimization"I decorated the getter and setter of my property with the [MethodImpl(MethodImplOptions.NoInlining)] attribute to prevent inlining. After that I got "only" a performance penalty of about 200 times slower than the native method call. To sum it up: My method is much slower as a native property (or wrapped function call) but still far away from being slow in absolute terms. If  this little class does help you to write nicer and cleaner code give it a try.
posted on Friday, February 10, 2006 8:39 PM

Feedback

# re: Call Properties through delegates and pass them by Reference 4/18/2006 10:21 PM Marc Brooks
For your next challenge, can you do it without any references to the property name AS A STRING? I want static/compile-time checking. See this post for why:

http://musingmarc.blogspot.com/2006/04/tale-of-two-implementations.html


# re: Call Properties through delegates and pass them by Reference 5/11/2006 2:41 AM Omer van Kloeten
Great minds think alike :P

http://weblogs.asp.net/okloeten/archive/2006/04/28/444363.aspx

# re: Call Properties through delegates and pass them by Reference 2/8/2007 11:03 AM Tedesco
There is another way to do that...

Create the delegates...
delegate T Getter<T>();
delegate void Setter<T>(T value);

Create function that 'runs' the delegates: for the string type they'll look like this (xx is a string property held by the application that declares the XXX function)...
private void XXX(Getter<string> x){xx = x();}
private void XXX(Setter<string> x){x(xx);}

When you need to pass the 'get' property to the application use the following call. To pass the Text getter of a TextBox control use...
XXX(delegate { return textBox1.Text; });

When you need to 'set' the control's Text property with the value received from the application use the following call...
XXX(delegate(string value) { textBox1.Text = value; });

If you have a way to receive a zip file I can send you a complete sample.

Regards, Tedesco.


# re: Call Properties through delegates and pass them by Reference 8/29/2008 2:23 AM rüya tabiri
thanks you.

# re: Call Properties through delegates and pass them by Reference 3/23/2009 4:49 AM Kevin Drzycimski
very nice, thank you for this.

the only thing i am a little disappointed about is the fact, that you hardcode the string "X" in this solution, i'll try to make strong typed version of my own and post it here if it does =)

# re: Call Properties through delegates and pass them by Reference 4/24/2010 10:09 PM Kevin Drzycimski
actually, here is a good solution for this problem. strongly typed and deduces at compile time:

http://stackoverflow.com/questions/491429/how-to-get-the-propertyinfo-of-a-specific-property/491486#491486

# re: Call Properties through delegates and pass them by Reference 4/25/2010 6:49 AM Alois Kraus
Cool I did not try it with Expressions yet. VB.NET is even easier but for C# I would guess this is the best solution although the amount of code generation could become a problem when many properties are fetched with the Expression method.

Yours,
Alois Kraus


# re: Call Properties through delegates and pass them by Reference 8/2/2011 8:33 PM nir
is there any way to create property for parametrized delegates.

public delegate void sss(int a);

public property sss Mydel
{
get;
set;
}

if any one have solution let me know at
niranjan.kala@live.in
Niranjan
http://www.niranjankala.in
http://developmentsolutionsjunction.blogspot.com


Post A Comment
Title:
Name:
Email:
Comment:
Verification: