Search code examples
c#constructorcoding-style

Best practice regarding code in constructor for initializing in C#?


I am learning C# and learning about classes, and I have a question regarding best practices in class initialization and constructors.

For instance, I was doing a practice exercise from Player's Guide C#, and this was the code I ended up with:

internal class Arrows
{
    /// <summary>
    /// Basic Practice class to ask for and define details of an arrow
    /// </summary>
    private enum _arrowhead
    {
        // Type of arrowhead
        Steel,
        Wood,
        Obsidian,
    }

    private enum _fletching
    {
        // Type of fletching
        Plastic,
        TurkeyFeathers,
        GooseFeathers,
    }
    
    private int _shaftLength = 60;   // default length of arrows is 60cm
    private float _shaftCostPerCm = 0.05f;
    private float _costOfArrow;

    public Arrows() {
        Console.WriteLine("Hello dear customer");
        Console.WriteLine("Welcome to my arrow shop\n");
        Console.WriteLine("First things first, what type of arrowhead would you like");
        foreach (string head in Enum.GetNames(typeof(_arrowhead))){
            Console.WriteLine(head + " = " + getHeadPrices(head) + " gold");
        }
        string _Head = Console.ReadLine();

        Console.WriteLine("\nTime now to select the type of fletching");
        foreach (string fletch in Enum.GetNames(typeof(_fletching)))
        {
            Console.WriteLine(fletch + " = " + getFletchingPrices(fletch) + " gold");
        }
        string _fletchingType = Console.ReadLine();

        Console.WriteLine("\nHow long do you want the arrows to be?");
        Console.WriteLine("I can manage to make arrows between 60 and 100 cm");
        _shaftLength = Convert.ToInt32(Console.ReadLine());

        _costOfArrow = singleArrowCost(_Head, _fletchingType, _shaftLength, _shaftCostPerCm);
        Console.WriteLine($"\nThe cost of one of these arrows is {_costOfArrow}");
    }

I just want to know is it better practice to write and prompt the user for all this outside the class and just pass the parameters in the constructor, or is it fine to pass all these statements to console inside the constructor and assign values accordingly.


Solution

  • Definitely get all your input outside of the class, and pass it as parameters. This is the principle of Separation of Concerns. It will make your class much easier to use, and the intent will be clear from the outside. Right now, someong using the constructor wouldn't know about all the Console processing. Also .. what if you wanted to get the input from some other place?

    Constructors should be used only to initialize the object to a usable state, do only what is required for that, and ideally not have any side effects.

    Some small logic is usually fine (e.g. calculated properties). For more complex logic, consider using a private constructor in combination with a static "factory method".

    You can read more about constructors and best practices here.