Set default value for Properties

Many times I needed to set a default value for a property.

For example at the property below

public string Property1 {get; set;}

I wanted a default value "Value1". The only way was to create a private field or to set it in code like Property1 = "Value1" somewhere.

What if I wanted to do this for all my properties ?

For this case i decided to create a custom attribute which does that thing. Takes a value and if the value of the current property is null sets it to the given value.

 

To be more specific let's begin with the custom attribute class:

 [global::System.AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
sealed class DefaultValueAttribute : Attribute
{
readonly object defaultValue;
readonly Type valueType;

public DefaultValueAttribute(object defaultValue, Type valueType)
{
this.valueType = valueType;
this.defaultValue = Convert.ChangeType(defaultValue, valueType);
}
public Type ValueType { get { return valueType; } }
public object DefaultValue
{
get { return defaultValue; }
}
}

Then we have a helper class with an extension method :

public static class DefaultValueAttributeHelper
{
public static void SetDefaultValues(this object obj)
{
Type t = obj.GetType();
foreach (var item in t.GetProperties())
{
foreach (var attr in item.GetCustomAttributes(typeof(DefaultValueAttribute), true))
{
DefaultValueAttribute val = ((DefaultValueAttribute)attr);
if (item.GetValue(obj, null) == null ||
((item.GetValue(obj, null).ToString() == "0") &&
(val.ValueType != typeof(string))))
item.SetValue(obj, val.DefaultValue, null);
}
}

}
}

And finally how this can be used  for example at an ASP.NET Page:

 

public partial class UserDetails : System.Web.UI.Page
{
public UserDetails()
{
this.SetDefaultValues();
}
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(StringProp + "<br>" + IntProp + "<br>" + (DoubleProp + 1));
}

[DefaultValueAttribute("6.11354", typeof(double))]
public double DoubleProp { get; set; }

[DefaultValueAttribute("6", typeof(int))]
public int IntProp { get; set; }

[DefaultValueAttribute("String1", typeof(string))]
public string StringProp { get; set; }


}

Well that's all ... This is really simple. Next step is to create an interface so the above attirbute can be used with custom objects.

If anyone has any improvements please let me know!

kick it on DotNetKicks.com

15 Comments

  • in the future, post also vb.net version, if possible :)

  • Cool solution, but what is wrong with this:

    public UserDetails()
    {
    // Set defaults.
    this.DoubleProp = 6.3;
    this.IntProp = 6;
    this.StringProp = "String1";
    }

    In all honestly in my opinion sometimes the simple solution is the way to goto, although the attribute solution is quite cool I just think setting in constructor would get the desired effect without the trickery.


    My 2 c :)

    Stefan

  • @Stefan :
    There is ABSOLUTELY nothing wrong with that. It is a simpler and better solution and i couldn't agree more with you.

    The above is just an alternative and i think it is more discrit in 3000 lines of code you because when you look at the property you know the default value right away.

    But again i couldn't agree more with you!

    John

  • I agree with Stefan. Your "clever" solution introduces A LOT of code for something that is wicked simple. More code == more potential for bugs. It also equates to less time writing code to actually make you app do what it is supposed to do.

  • I agree that putting the "default value" near the property declaration is MUCH more expressive than hiding it in a constructor.

    I didn't even think ASP.NET pages had a constructor. Obviously they do, but I never see it used by anyone.

    Do the ones who don't like this make large ASP.NET apps + pages? I have a solution similar to this, but its not nearly as elegant, since most of my page-level properties are backed to viewstate (instead of an auto-property). Since code is often collapsed, that "default value" is not visible. I'm definitely going to take this technique and try and use it with my viewstate backed properties (so the default value is not hidden in collapsed code in outline mode).

  • Unfortunately upon experimentation, I can't use this technique; since I don't actually want to "set" the default value into viewstate, but only return it in the getter, and the default value is often used, I fear it will be a perf hit since it would have to look up the attribute's value so often.

  • @Bertkid
    What exactly are you trying to achive? I made something but i am not quite sure what you mean. Could you please be more specific?

  • Doesnt the System.ComponentModel.DefaultValue attribute achieve the same thing you are doing? Why are you trying to rewrite functionality that comes out of the box?

  • I would rather just set the values in the constructor, its clear, its explicit, you don't need to resolve the type and its checked at build time.

    I do agree that the automatic properties are not very useful when you need a default. When I need a default value, I use a backing variable.


    The DefaultValue Attribute only provides a hint to tools, telling them what the expected default value is.


  • I really like this idea, but I have to agree with the other commentors. Simple assignments in the constructor is a better solution. My main reasons for this are:

    - People expect default assignments in the constructor
    - The reflection being used is slower than a constructor assignment
    - On a side note, foreach is slower than for statements
    - The attribute uses object as the type of the value passed to the attribute so you will encounter boxing and unboxing of the value

    I still like the solution though...

  • If you move the Convert.ChangeType() call into SetDefaultValues() and use t.PropertyType there, you can eliminate ValueType entirely. (actually, since it's going from an object to an object, I don't think you need the ChangeType at all)

    You can also pass the default value itself as it's native type:

    [DefaultValueAttribute(6)]
    public int IntProp { get; set; }

    [DefaultValueAttribute("String1")]
    public string StringProp { get; set; }

  • IMHO it is not very good idea to hardcode default values. At least you should't hardcode the defaults that may change.

    Using attributes may be the best solution if you keep default values in application config and with attributes you are saying the name of the key of default value that corresponds to property.

    Something like this:
    [DefaultValueAttribute("IncomeTaxRate")]
    public decimal IncomeTaxRate { get; set; }

  • Set default value for properties.. Smashing :)

  • Set default value for properties.. Awful :)

  • Hey Therefore i'm creating a extremely gang of great vocalists as well as tune in to you the great experience you beautiful noises mixture jointly and when I had time to ever before head over to North america as well as speak to it would be eaiest our one large desire is always to satisfy you once more of course, if zero I really could be with you possibly perform so I might load our desire. I really do not necessarily understand when is it best to return to Europe nevertheless think several but not nearly therefore conceivably perhaps even much more nevertheless myself of course, if you ever before seem to check out North america, as well as certainly I would possibly be pleased once we include your current routines for the lazy ever before have noticed. If only you take care for the whole set every success as well as delivers great routines specially great in your administration. All over again If only take care for the great moment.

Comments have been disabled for this content.