C#: How to set default value for a property in a partial class?

71,342

Solution 1

Updated for C# 6

C# 6 has added the ability to assign a default value to auto-properties. The value can be any expression (it doesn't have to be a constant). Here's a few examples:

// Initialize to a string literal
public string SomeProperty {get;set;} = "This is the default value";

// Initialize with a simple expression
public DateTime ConstructedAt {get;} = DateTime.Now;

// Initialize with a conditional expression
public bool IsFoo { get; } = SomeClass.SomeProperty ? true : false;

Original Answer

Automatically implemented properties can be initialized in the class constructor, but not on the propery itself.

public SomeModel
{
    IsSomething = false;
    SomeList = new List<string>();
}

...or you can use a field-backed property (slightly more work) and initialize the field itself...

private bool _IsSomething = false;
public bool IsSomething
{
    get { return _IsSomething; }
    set { _IsSomething = value; }
}

Update: My above answer doesn't clarify the issue of this being in a partial class. Mehrdad's answer offers the solution of using a partial method, which is in line with my first suggestion. My second suggestion of using non-automatically implemented properties (manually implemented properties?) will work for this situation.

Solution 2

The first property (IsSomething) is a boolean. It will be false by default.

The second property, since it's a reference type, will default to null without any effort on your part. You don't need to touch the constructor, since reference types (classes) will automatically start off as null in .NET.

If you wanted to use a non-default value, you'd have two options -

First, use a backing storage field:

private bool isSomething = true;
public bool IsSomething {
    get { return this.isSomething; }
    set { this.isSomething = value; }
}

Second option - add it to the constructor.

Note that the first option has no extra overhead - it's basically what the compiler does when you use an automatic property.

Solution 3

You can't have two constructors in two parts of a partial class. However, you can use partial methods to accomplish something like it:

// file1:
partial void Initialize();
public Constructor() {
    // ... stuff ... initialize part 1
    Initialize();
}

// file2:
void Initalize() {
    // ... further initializations part 2 might want to do
}

If no parts of a partial class defines the partial method, all calls to it would be omitted.

Solution 4

WARNING for users of WCF partial classes

If you're trying to add a property to a WCF proxy class (generated by Add Service Reference) you might be surprised to find that private fields aren't initialized because apparently no constructor at all is called.

If you attempt to do this (as suggested in some other answers) it won't ever get called :

    private bool _sendEmail = true;

This has nothing to do with whether the field is in a partial class or not.

What you have to do is add an [OnDeserialized] attribute which lets you do further initialization to the object. This is part of System.Runtime.Serialization so is only useful in the context of serialization when using DataContractSerializer.

public partial class EndOfDayPackageInfo
{
    [OnDeserialized()]
    public void Init(StreamingContext context)
    {
        _sendEmail = true;
    }

    private bool _sendEmail;
    public bool SendEmail
    {
        get
        {
            return _sendEmail;
        }
        set
        {
            _sendEmail = value;
            RaisePropertyChanged("SendEmail");
        }
    }

}

Another approach is to 'lazy load' the property - but this approach is much less elegant.

    private bool _sendEmail;
    private bool _sendEmailInitialized;

    public bool SendEmail
    {
        get
        {
            if (!_sendEmailInitialized)
            {
                _sendEmailInitialized = true;
                _sendEmail = true;  // default value
            }

            return _sendEmail;
        }
        set
        {
            if (!_sendEmailInitialized)
            {
                // prevent unwanted initialization if 'set' is called before 'get'
                _sendEmailInitialized = true;
            }

            _sendEmail = value;
            RaisePropertyChanged("SendEmail");
        }
    }

Solution 5

To this, don't use automatic property but the old way

YourType _yourParameter = yourDefaultValue;
public YourType YourParameter
{
   get{return _yourParameter;}
   set{_yourParameter=value;}
}
Share:
71,342

Related videos on Youtube

Roee Adler
Author by

Roee Adler

Lover of technology and science and Battlestar Galactica.

Updated on July 09, 2022

Comments

  • Roee Adler
    Roee Adler almost 2 years

    I'm very new to C# so please bear with me...

    I'm implementing a partial class, and would like to add two properties like so:

    public partial class SomeModel
    {
        public bool IsSomething { get; set; }
        public List<string> SomeList { get; set; }
    
        ... Additional methods using the above data members ...
    }
    

    I would like to initialize both data members: IsSomething to True and SomeList to new List<string>(). Normally I would do it in a constructor, however because it's a partial class I don't want to touch the constructor (should I?).

    What's the best way to achieve this?

    Thanks

    PS I'm working in ASP.NET MVC, adding functionality to a a certain model, hence the partial class.

    • John Saunders
      John Saunders almost 15 years
      Those are already the default values for those types. You don't need to do anything.
    • Roee Adler
      Roee Adler almost 15 years
      I edited the question to reflect values that are not the "natural" defaults.
  • grenade
    grenade almost 15 years
    SomeList = new List<string>**()**;
  • Roee Adler
    Roee Adler almost 15 years
    Regarding your first suggestion, is it considered "good practice" to do so? It will certainly be easier, but feels like "code smell"...
  • STW
    STW almost 15 years
    @RaxL I'm on the fence about the smell of it. Initialization logic is a fairly normal part of OO development; provided that the developers working on the system follow the same practices then I don't htink it would be an issue.
  • STW
    STW almost 15 years
    As Reed pointed out in his comment the value-types will initialize with a default value (0 for int, false for bool...) but the reference types will initialize to null/Nothing. So in his case IsSomething = false and SomeList = null
  • STW
    STW almost 15 years
    +1 for pointing out the different behaviors of value/reference types.
  • Roee Adler
    Roee Adler almost 15 years
    @Yooder: this answer was provided when the question still asked for defaults of False and null. Please retract your -1, it's unfair for @Programming Hero
  • Paul Turner
    Paul Turner almost 15 years
    Moving the goal posts mid-game? No fair!
  • NotMe
    NotMe over 13 years
    How interesting. Makes sense in a twisted way.
  • aruno
    aruno over 13 years
    ya but very confusing at first. just discovered this today and thought it was a WPF binding issue until I finally realized it was WCF. turns out they call this method which circumvents calling any constructor : msdn.microsoft.com/en-us/library/…
  • Dylan Meador
    Dylan Meador over 12 years
    Thanks, this was exactly my issue.
  • ncubica
    ncubica over 11 years
    what does RaisePropertyChange method? does this method is from .net framework??
  • H35am
    H35am over 6 years
    Note this, adding any code (including this answer) in your auto generated class will wiped away after a refresh of your model.
  • STW
    STW over 6 years
    @H35am you should never modify generated classes (scaffolding is a different story--you never "refresh" or re-generate scaffolding)
  • H35am
    H35am over 6 years
    But how do you implement your answer in a partial class? Since the problem states that some functionality is needed in the Model class that is auto generated.