Click here to Skip to main content
Email Password   helpLost your password?

Introduction

C# 3.0 introduces a great new feature called Automatic Properties, and if you haven’t already read about them, I would encourage you to read Scott Guthrie's introductory post.

As great as they are and as much time as they save, Automatic Properties have a serious drawback – you can’t set the default value of the property. Instead, the compiler will initialize value properties to 0, reference properties to null, and enum’s to the first member, and while this might work for some applications, it wasn’t working for mine.

Background

When I thought about the implementation, two options became apparent. One, I could create a base object class and have all of my classes inherit from this base class. This however isn’t a great solution because a number of my classes inherit from other classes outside of my control, and since .NET does not support multiple inheritances, it was clear this wasn’t going to work. To my rescue was the also new C# 3.0 feature, Extension Methods. If you haven’t already heard about Extension Methods, I’d recommend reading another one of Scott Guthrie's blog posts about them.

Using the Code

Using the code requires that you decorate your properties with an attribute already available in the System.ComponentModel namespace – if you haven’t already guessed it, it’s the aptly named DefaultValueAttribute attribute. As well, it requires a quick call to the InitDefaults() extension method from the constructor which I will discuss a bit later.

The attached code supplies a demo implementation of the TestObject and TestObjectInherited classes:

public class TestObject
    {
        public TestObject()
        {
            this.InitDefaults();
        }

        [DefaultValue(-45)]
        public int DefaultInt
        {
            get;
            set;
        }

        [DefaultValue(10.23)]
        public double DefaultDouble
        {
            get;
            set;
        }

        [DefaultValue(true)]
        public bool DefaultBool
        {
            get;
            set;
        }

        [DefaultValue(TestEnum.Value2)]
        public TestEnum DefaultEnum
        {
            get;
            set;
        }

        [DefaultValue("DefaultString!")]
        public string DefaultString
        {
            get;
            set;
        }

        public string StringWithoutDefault
        {
            get;
            set;
        }

        public string ValueOfPrivateProperty
        {
            get
            {
                return PrivateProperty;
            }
        }

        [DefaultValue("This is a private property!")]
        protected string PrivateProperty
        {
            get;
            set;        
        }
    }

The magical InitDefaults() method is implemented as an extension method which uses reflection to set the value of the properties to the default value:

public static void InitDefaults(this object o)
        {
            PropertyInfo[] props = o.GetType().GetProperties(BindingFlags.Public | 
                BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);

            for (int i = 0; i < props.Length; i++)
            {
                PropertyInfo prop = props[i];                

                if (prop.GetCustomAttributes(true).Length > 0)
                {
                    object[] defaultValueAttribute = 
                        prop.GetCustomAttributes(typeof(DefaultValueAttribute), true);

                    if (defaultValueAttribute != null)                    
                    {
                        DefaultValueAttribute dva = 
                            defaultValueAttribute[0] as DefaultValueAttribute;
                        
                        if(dva != null)
                            prop.SetValue(o, dva.Value, null);                                
                    }
                }
            }
        }

Points of Interest

I decided to support initializing the default value of properties in inherited classes, but if you don’t want this behavior, you can simply pass false to GetCustomAttributes().

if (prop.GetCustomAttributes(false).Length > 0)
                {
                    object[] defaultValueAttribute = prop.GetCustomAttributes
                        (typeof(DefaultValueAttribute), false);

                    if (defaultValueAttribute != null)                    
                    {
                        DefaultValueAttribute dva = 
                            defaultValueAttribute[0] as DefaultValueAttribute;
                        
                        if(dva != null)
                            prop.SetValue(o, dva.Value, null);                                
                    }
                }

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
Generalover-design?
ffffffffffffffffffff
10:03 29 Oct '08  
This is creative and a good demonstration of some newer language features, but it strikes me as an overly complicated solution to a simple problem. You need to call code from the constructor anyway, so why not just set the defaults of your automatic properties there?
GeneralDiffent approach
Günther M. FOIDL
1:01 8 Oct '08  
In my approach (same reflection things as in your article) I have a class that sets the default values.
Classes where automatic properties are used have then to be inherited from this class.

public class AutomaticProperties
{
public virtual void InitDefaults(object o)
{
PropertyInfo[] propteryInfos =
o.GetType().GetProperties(
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.Static);

foreach (PropertyInfo pi in propteryInfos)
{
if (pi.GetCustomAttributes(true).Length > 0)
{
object[] attributes =
pi.GetCustomAttributes(
typeof(DefaultValueAttribute),
true);

if (attributes != null)
{
DefaultValueAttribute dva =
attributes[0] as DefaultValueAttribute;

if (dva != null)
pi.SetValue(o, dva.Value, null);
}
}
}
}
//---------------------------------------------------------------------
public AutomaticProperties()
{
InitDefaults(this);
}
}

The constructor of the base class gets executed when an inherited class is initialized the code for the (inherited class) need no extension.

For instance:
public class MyClass : AutomaticProperties
{
[DefaultValue(true)]
public bool boolWert { get; set; }

[DefaultValue(666)]
public int intWert { get; set; }

[DefaultValue("Günther")]
public string stringWert { get; set; }
}

Regards Günther
RantVote for initialization to be added as a language feature.
Laughing.John
14:08 23 Aug '08  
Good article, but as someone else said it's ridiculous to have to go to this trouble. Mad

My views are that I quite like automatic properties as they save a lot of typing and more often than not you don't have any extra code in the getter or setter. However the lack of initialization is very frustrating.

It's made worse because Microsoft have changed the prop snippet to create automatic properties instead of normal ones (note that you can add the old one back in). This means that if you need to initialize a property you either have to do it in the constructor or type the full syntax by hand which means it's even slower. Adding it in the constructor also defeats the point - these are meant to save typing!!!

And there is nothing on the refactor menu to let you change an automatic property into a full one.

I've created a request on Microsoft connect if you want to vote:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=361647[^]
GeneralI don't think its a good idea
Jorge Bay Gondra
4:18 22 Aug '08  
Hi!
I don't think its a good idea lose performance (using reflection and an extra method) just for an elegance in code.
I think the best idea for default values in properties is to use a private variable the old fashion way:
private [type] [var_name];
public [type] [prop_name]
{
get{return [var_name]}
set{[var_name] = value}
}
Best regards,
Jorge
Desarrollo sitios web
GeneralAnother option
Ajek
12:02 20 May '08  
Hi,

I find this solution a bit over the top actually.

"Automatic properties" are used to save you time-typing for easy properties. If you need something specific you can't use them. You then have to use the old way.

The need to have a default value however is a common one.

My solution to this problem is actually simple and one I allready use right now in .NET2.0

class MyClass
{
public int MyProp {get; set;}
public MyClass()
{
Init();
}
private void Init()
{
MyProp = 5;
}
}

Instead of setting the default values through attributes, I just set them in code in a method (Init). You can call this method then in all your c'tors.

It's the same amount of typing. Just simpler (in my opinion).

As to the inherited classes. I don't really care about their properties in my base-class. The inherited class should know how to initialise itself during creation, not it's base class

Best regards,
Ike
GeneralRe: Another option
nsimeonov
17:32 9 Jun '09  
While I agree with you there are 2 things to consider:

1. constructor's code will not be next to the property, so if you have a really long list of properties you should scroll up and down to see their default values
2. the setter will be invoked, hence in a class that inherited your base class it may behave differently (which is actually the case with the solution in this article too).

Ideally MS will enhance the syntax to something like this:

  public int MyProp { get; set; default=123; }

But until then I too believe a constructor is the best solution especially considering the performance impact when using reflection...

Regards,
Nick
GeneralA opinion
Ricky Wang
20:57 19 May '08  
In my period of developing application, the default values (according to business domian) at best can be set out of the codes. Otherwise, each time users change the requirement you must go into the cluttering code to interpolate attribute.

Take nothing on looks; take everything on evidence.
- Charles Dickens

GeneralI'd do it differently...
PIEBALDconsult
14:49 14 May '08  
I'd do it differently... but no one here should be surprised about that. Big Grin

I'd eliminate some of the local variables by using foreach rather than for.

I'd eliminate the extra check for attributes.

I might also add type checking to be sure the property can be set to the value.

Also, if you instantiate a large number of a particular type and then perform InitDefaults on each, you'll hit Reflection a number of times, at considerable cost, always getting the same results, so I suggest caching the results to improve performance.


public static void InitDefaults ( this object o )
{
foreach
(
System.Reflection.PropertyInfo prop
in
o.GetType().GetProperties
(
System.Reflection.BindingFlags.Public
|
System.Reflection.BindingFlags.NonPublic
|
System.Reflection.BindingFlags.Instance
|
System.Reflection.BindingFlags.Static
)
)
{
foreach
(
System.ComponentModel.DefaultValueAttribute dva
in prop.GetCustomAttributes
(
typeof(System.ComponentModel.DefaultValueAttribute)
,
true
)
)
{
if ( o.GetType().IsAssignableFrom ( dva.Value.GetType() ) )
{
prop.SetValue ( o , dva.Value , null ) ;
}
}
}
}

(Well, that compiles, but I'm not sure the type check will work, I haven't tested it.)
GeneralRe: I'd do it differently...
Seishin#
2:56 15 May '08  
if ( o.GetType().IsAssignableFrom ( dva.Value.GetType() ) ) {
prop.SetValue ( o , dva.Value , null ) ;
}
How come you did't write almost every word in separate line, like the rest of your code..

>I'd eliminate some of the local variables by using foreach rather than for.
foreach is proven to be less efficient.

life is study!!!

GeneralRe: I'd do it differently...
PIEBALDconsult
6:56 15 May '08  
Aw, crap, you're right! I forgot to split up the call to SetValue! D'Oh!


Seishin# wrote:
foreach is proven to be less efficient.

Do you have numbers?
foreach is more readable, so unless it's much less efficient, I'll use it.
GeneralRe: I'd do it differently...
PIEBALDconsult
8:39 15 May '08  
Seishin# wrote:
foreach is proven to be less efficient.

Here are some numbers; summing the elements of a 100000-element array of longs 100000 times:

for takes 00:01:40.6127095
foreach takes 00:01:46.2636235

(Pentium Dual, 1.8 GHz, 1GB RAM, WinXP)

Although that's about a 5% difference I don't consider it to be significant.

Me: "Saving five seconds over a minute-and-a-half? Big fat hairy deal."

I'll gladly take the readability of foreach in a case like this.
GeneralRe: I'd do it differently...
Seishin#
9:30 15 May '08  
http://www.codeproject.com/KB/cs/foreach.aspx[^]

life is study!!!

GeneralRe: I'd do it differently...
PIEBALDconsult
10:45 15 May '08  
He says:

"
foreach copies the current array to a new one
"

which is ridiculous. And he doesn't give any numbers.

It's also possible that the enumerator for arrays has been improved since he wrote that.
GeneralRe: I'd do it differently...
Seishin#
10:47 15 May '08  
well, his article isn't one of the best, but I read one here at CP that gave numbers.. and the numbers spoke to me.. unfortunatelly I can't seem to find it now.. when I do I'll surely post it here for you.

life is study!!!

GeneralRe: I'd do it differently...
PIEBALDconsult
11:15 15 May '08  
Any comments on my numbers?
GeneralI Don't See The Value In Automatic Properties
John Simmons / outlaw programmer
12:26 14 May '08  
I'm not arguing the merit of your article, but instead am arguing the merit of automatic properties. Rather, I'm commenting on the value of automatic properties, especially given that you can't set default values without adding code. So...

I'm way old school, so it looks to me like it obfuscates the code. The following

private int m_myValue = 1;

public int MyValue
{
get { return m_myValue; }
set { m_myValue = value; }
}

is much easier to maintain than this:

public MyValue { get; set; }

Just because you *can* hide the minutia doesn't mean you should. Next thing you know, .net will ooze into the hell that is "typeless languages".

What they should really do is give us a way to add properties through the Class View pane. All we should have to do is specify the name of the data member, select accessibility and type from drop-down lists, and check a couple of boxes regarding the presence of set and get. The code should be automatically added for us based on what we select. THAT would be a productivity enhancement.

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: I Don't See The Value In Automatic Properties [modified]
PIEBALDconsult
14:16 14 May '08  
John Simmons / outlaw programmer wrote:
add properties through the Class View

That would be an IDE feature, not a language feature.

P.S. But, yeah, automatic properties and extension methods both.

modified on Wednesday, May 14, 2008 7:50 PM

GeneralRe: I Don't See The Value In Automatic Properties
William E. Kempf
7:47 15 May '08  
I've blogged about this, calling automatic properties the "lamest addition" to C# (http://wekempf.spaces.live.com/blog/cns!D18C3EC06EA971CF!234.entry[^]).

I can't agree about extension methods. They are vital to LINQ, if for nothing else. There's also a lot of very nice things that can be accomplished with them that have extremely sub-optimal solutions without them.

As for this particular article... I don't find it useful. The extra code required here reduces the little productivity benefit you get from automatic properties. Worse, you suffer performance wise from this. If you are going to use automatic properties, what's wrong with initializing them in the constructor?


public class Foo
{
public Foo()
{
Bar = string.Empty;
}

public string Bar { get; set; }
}


William E. Kempf

GeneralRe: I Don't See The Value In Automatic Properties
PIEBALDconsult
8:53 15 May '08  
William E. Kempf wrote:
They are vital to LINQ

I don't use LINQ (I've only seen it in a demo at the {launch} event), but knowing that some here do I decided not to add var to my post. Big Grin


William E. Kempf wrote:
extremely sub-optimal solutions without them

I am interested in seeing one (that doesn't use LINQ).


William E. Kempf wrote:
what's wrong with initializing them in the constructor?

Indeed; wouldn't that be the logical place to call InitDefaults anyway?
GeneralRe: I Don't See The Value In Automatic Properties
William E. Kempf
9:37 15 May '08  
PIEBALDconsult wrote:
William E. Kempf wrote:
extremely sub-optimal solutions without them


I am interested in seeing one (that doesn't use LINQ).

A simple example is providing method overloads for interfaces. The options without extension methods are to put the overloads in the interface, requiring every implementation to have to implement them (and possibly even change the intended contract), or to use static helper methods in some class. While the latter *IS* exactly what you're doing with extension methods, the complexity for consumers of the API has been drastically reduced.

That's just one example. There's a lot of other examples in the wild. For instance, fluent interfaces are much easier to achieve using extension methods.

William E. Kempf

GeneralRe: I Don't See The Value In Automatic Properties
PIEBALDconsult
10:29 15 May '08  
William E. Kempf wrote:
The options without extension methods are to put the overloads in the interface, requiring every implementation to have to implement them (and possibly even change the intended contract),

Well, my understanding is that extension methods are for when one doesn't have the ability to modify the class/interface. If you do have control over the class/interface, and it makes sense to add the method, then go right ahead and add it; if not, why use an extension method to make it look like you did?

There are two things I don't like about extension methods:
They require a using directive.
When the code is printed out or posted online, or otherwise not displayed in VS, I can't tell that a particular method is an extension method.

Oh, and what if they who do control the class/interface later add a method that matches the extension method but does something else? (I'll have to check that out myself.)


At any rate, I'm still not sold.
GeneralRe: I Don't See The Value In Automatic Properties
William E. Kempf
10:42 15 May '08  
PIEBALDconsult wrote:
Well, my understanding is that extension methods are for when one doesn't have the ability to modify the class/interface. If you do have control over the class/interface, and it makes sense to add the method, then go right ahead and add it; if not, why use an extension method to make it look like you did?

With a class, that's absolutely correct. I explained why it's not ideal with an interface. "Just adding it" to the interface means that every implementation has to provide an implementation that should be THE EXACT SAME implementation in every case.

PIEBALDconsult wrote:
There are two things I don't like about extension methods:
They require a using directive.

So does everything else. In all of the use cases I gave, however, the extension method resides in the SAME namespace, so no extra using is required.

I will give you a partial point (maybe an 1/8 point) here. The IDE automates adding the using most of the time, but with extension methods it can't. This causes me a little grief from time to time with LINQ. It's not the end of the world, however.

PIEBALDconsult wrote:
When the code is printed out or posted online, or otherwise not displayed in VS, I can't tell that a particular method is an extension method.

The classic counter argument, and it holds NO water with me. If I'm reading code, not maintaining it, why would I care? If I'm maintaining, I'm going to be using developer tools that will reveal what I need to know.

PIEBALDconsult wrote:
Oh, and what if they who do control the class/interface later add a method that matches the extension method but does something else? (I'll have to check that out myself.)

The non-extension method will be called.

William E. Kempf

GeneralRe: I Don't See The Value In Automatic Properties
Steven Berkovitz
10:44 15 May '08  
You can identify extension methods because the signature starts with "this" ie: ExtensionName(this object o)

-Steven

GeneralRe: I Don't See The Value In Automatic Properties
William E. Kempf
10:46 15 May '08  
That's not the argument. Given this:

Foo foo = new Foo();
foo.Bar();

Is Bar() a member of Foo, or an extension method?

Again, though, I don't buy this argument. If I'm reading code, why would I care? If I'm maintaining code, my tools will tell me the answer.

William E. Kempf

GeneralRe: I Don't See The Value In Automatic Properties
PIEBALDconsult
10:49 15 May '08  
I meant in a call to one: someobject.somemethod ( ... )


Last Updated 14 May 2008 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010