Answered C# Constuctors and Properties

  • Saturday, September 22, 2012 4:22 PM
     
     
        public Planet(string planetName,string planetLocation,string galaxy)
            {
                //Is this okay to do in C#?
                Name = planetName;
                this.planetLocation = planetLocation;
                this.galaxy = galaxy;

                /*
                 *
                 *
                 */

     
            }

            public String Name
            {
                get
                {
                    return planetName;
                }
                set
                {

                    if (value == null)
                    {
                        throw new ArgumentNullException("Name cannot be Null");
                    }

                    this.planetName = value;

                }

            }



    I created this simple example to show what I mean.

    1. Is it okay for a C# constructor to call its own Getter/Setter Property?  If the Name is null the ArgumentNullException will be thrown.
    2. If is not recommended to call the setter property from the constructor, then how do you implement exceptions in the constructor to ensure that the name field isn't blank? or in other words if I say Planet myPlanet = new Planet(null,"9999999","Milky Way"); How do I ensure that the exception is thrown if I create my object this way?
    • Edited by Oasisfactor Saturday, September 22, 2012 4:23 PM
    •  

All Replies

  • Saturday, September 22, 2012 4:33 PM
     
      Has Code

    You should use try-catch stetement around your "Planet myPlanet = new Planet(null,"9999999","Milky Way");"

    try
    {
        Planet myPlanet = new Planet(null,"9999999","Milky Way");
    }
    catch (Exception ex)
    {
        ///TODO:  log error
    }


    Roar Jørstad
    Senior Consultant, EVRY as
    Blog: Notebook, trick & tips

  • Saturday, September 22, 2012 4:53 PM
     
     

    No, dont use any try, catch block, because we can avoid 100% using it only by the code - with the right code I mean.

    To get back to OP code example:

    In short to answer: if it works, I dont see any problem why not using it this way too.

    In practice I woldnt use this kind of code, to call the property from the class`s constructor. Why? Because its pointless to have a property in 1st place - then you can simlly swap it with a field. Property is means to be propery SET and when is set, to be RETRIVED (get).

    So 1st of all to access to class`s memebers (property included of course), you need a class reference (variable that you create a new instance of a class).

    Then set the property when needed, and get the value back from it when needed also.


    Mitja

  • Saturday, September 22, 2012 5:21 PM
     
     Answered Has Code

    To answer the questions: 

    1. that is perfectly fine

    2. no need to discuss since 1. is ok

    and to Mitja Bonca: you use the properties in your constructor if you have no access to the underlying data field. as in 

    public class Foo
    {
       public int NumberValue { get; set; }
    
       public Foo (int number)
       {
    	NumberValue = number;  // property access here
       }
    }

    - Walter Knupe

  • Saturday, September 22, 2012 5:47 PM
     
     

    Even system classes raise exceptions from constructors. For example the constructor of FileStream throws ArgumentNullException if the path is null.

  • Saturday, September 22, 2012 8:29 PM
     
     

    I just want to add more thoughts.

    You should always handle all possible exceptions in your constructor.

    The idea is ideally you should write classes that don't have intricate constructors that might cause exceptions.

    So the point is your constructor should never throw an exception to the code that's creating an instance of your class.

    Secondly- It should not be possible to create an instance of your class in an invalid or partially initialized state.

    If handling all exceptions in your constructor makes it possible to create an instance that's invalid/unusable, you should rewrite your class.

    If you can't rewrite your class, ideally you should be, at least your class methods that throw exceptions rather than the constructor.

    The code that uses the instance's methods will be within a try/catch block than the code that creates the instance. 

    Hope this is useful.


    Mark it as helpful if so!!! thanks, Mithilesh

  • Monday, September 24, 2012 1:07 PM
     
     

    So the point is your constructor should never throw an exception to the code that's creating an instance of your class.

    Secondly- It should not be possible to create an instance of your class in an invalid or partially initialized state.

    You shouldn't be able to create an instance in an invalid state, but you shouldn't throw exceptions from the constructor??? How do you do that?

    Of course, you should throw exceptions from the constructor if the arguments are invalid.

  • Monday, September 24, 2012 2:03 PM
     
     

    I just want to add more thoughts.

    You should always handle all possible exceptions in your constructor.

    The idea is ideally you should write classes that don't have intricate constructors that might cause exceptions.

    So the point is your constructor should never throw an exception to the code that's creating an instance of your class.

    Secondly- It should not be possible to create an instance of your class in an invalid or partially initialized state.

    If handling all exceptions in your constructor makes it possible to create an instance that's invalid/unusable, you should rewrite your class.

    If you can't rewrite your class, ideally you should be, at least your class methods that throw exceptions rather than the constructor.

    What's your basis for making these assertions?  There are a lot of classes in the BCL that throw exceptions from constructors (normally if invalid parameters are provided).  It is most certainly better than not throwing an exception and returning an instance in an invalid state.  If you're deferring the work until a method is called then in what way are you improving the situation?  If you do that then you're creating an instance that is invalid from the time it is constructed until that method executes.
  • Monday, September 24, 2012 4:31 PM
     
     

    In my opinion, not to do any work in instance constructors probably comes from hybrid C/C++ practice (where exceptions in constructors may be problematic, thus requiring Initialize() methods doing actual work).

  • Monday, September 24, 2012 4:35 PM
     
     
    Do minimal work in the constructor. Constructors should not do much work other than to capture the constructor parameters. The cost of any other processing should be delayed until required.
  • Monday, September 24, 2012 4:38 PM
     
     
    Do minimal work in the constructor. Constructors should not do much work other than to capture the constructor parameters. The cost of any other processing should be delayed until required.


    So then if I want to create my object like this:

    Planet myPlanet = new Planet(null,"9999999","Milky Way");

    How would I ensure that the name field isn't blank and to throw an exception if it is blank?

    Can I call the setter property from the constructor?

  • Monday, September 24, 2012 4:49 PM
     
     

    In my opinion, not to do any work in instance constructors probably comes from hybrid C/C++ practice (where exceptions in constructors may be problematic, thus requiring Initialize() methods doing actual work).

    C# isn't c/c++.  In c/c++ your advice makes sense.  This is due to the fact that in c/c++ all types are value types.  You'll notice that for value types in C# there will always be a default constructor that can never do any work other than zero out the bits in that structure.  Constructing value types needs to (at least have the potential to) be constructed with a guarantee of success.

    This doesn't apply to reference types.

    Unlike value types, they never need to be constructed when they aren't supposed to actually exist.  In fact, you shouldn't be constructing them until you are sure they should exist and that you have everything needed to ensure that the instance is "valid".  Value types on the other hand need to have default values so that variables can be initialized before they are used, arrays can have something in them when they are created and before they are populated, etc.  For reference types `null` is able to handle all of those situations.

    For all of these reasons it's actually bad practice in C# to have a constructor that does nothing, or not much, and a public "initialize" method that actually constructs the object.


  • Monday, September 24, 2012 4:52 PM
     
     

    How would you go about fixing my problem then. How would you properly do this:

    Planet myPlanet = new Planet(null,"9999999","Milky Way");

    Then throw an exception should the name field be blank?
  • Monday, September 24, 2012 5:00 PM
     
     

    How would you go about fixing my problem then. How would you properly do this:

    Planet myPlanet = new Planet(null,"9999999","Milky Way");

    Then throw an exception should the name field be blank?
    I would say that the code that you have shown is fine just the way it is.
  • Monday, September 24, 2012 5:03 PM
     
     
    Alrighty, so my code calls the setter property in the constructor and the setter takes care of any exceptions that might pop-up. Alright, so to restate, the code I have in my original post at the top is alright, calling the setter from the constructor is okay to do?


    • Edited by Oasisfactor Monday, September 24, 2012 5:19 PM
    •  
  • Monday, September 24, 2012 5:41 PM
     
     Answered
    Alrighty, so my code calls the setter property in the constructor and the setter takes care of any exceptions that might pop-up. Alright, so to restate, the code I have in my original post at the top is alright, calling the setter from the constructor is okay to do?
    Yes.
    • Marked As Answer by Oasisfactor Monday, September 24, 2012 5:43 PM
    •