Home > Software design >  Constructors and properties being set to private or public
Constructors and properties being set to private or public

Time:09-08

I am creating a class in C# and am being told that all of my properties should be public. I was taught that information hiding is common in C but idk if it is the same is C# or if the convention for doing so is different. The first example is how I was taught to do it. The 2nd example is how I am being taught to implement this class now. My question is this: Will this prevent me from using any of the properties with other classes or will it all work because of the constructor making them public?

Thank you all in advance

    class Book
    {
        string Title = null;
        string Author = null;
        int Year = 0;
        string CoverType = null;

        public Book (string aTitle, string anAuthor, int aYear, string aCoverType)
        {
            Title = aTitle;
            Author = anAuthor;
            Year = aYear;
            CoverType = aCoverType;
        }

Separation of examples

    
    public class Book
    {
        public string Title = null;
        public string Author = null;
        public int Year = 0;
        public string CoverType = null;

        public Book (string aTitle, string anAuthor, int aYear, string aCoverType)
        {
            Title = aTitle;
            Author = anAuthor;
            Year = aYear;
            CoverType = aCoverType;
        }


CodePudding user response:

Will this prevent me from using any of the properties with other classes

No. That's the definition of having public modifier.

However, as written in the Microsoft documentation public fields are "Generally not recommended"

The common approach is to expose properties with backing fields.

CodePudding user response:

public will make your fields accessible, but I think you want properties with auto getters/setters here.

The principle of encapsulation is one of the most important notions in object-oriented design. This principle states that data stored inside an object should be accessible only to that object.

A useful way to interpret the principle is to say that a type should be designed so that changes to fields of that type (name or type changes) can be made without breaking code other than for members of the type. This interpretation immediately implies that all fields must be private.

❌ DO NOT provide instance fields that are public or protected.

You should provide properties for accessing fields instead of making them public or protected.

https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/field

CodePudding user response:

You should separate properties and fields, i.e.

private int year = 0; // field
public int Year { get { return year;}} // Property, wrapping the field
public int Year2  => year; // Same as above, using more compact syntax
public String Author {get;} // auto-property, automatically adds a hidden field

The typical rule is to keep fields private, and if you need public access, wrap them in a property, or use an auto property. So it usually does not make much sense to make properties private, since the goal is usually to expose the underlying field.

I would also recommend using readonly properties whenever practical, i.e. {get;} or {get; init;}. If the property can never change, there is usually less problems with making it public.

CodePudding user response:

I suggest using properties instead of fields:

  • Let's set Title, ..., CoverType once in the consructor and prevent them form occasinal (erroneous) modifications
  • Let's validate input arguments, let's not use null as placeholder.

Code:

public class Book
{
    public string Title     { get; }
    public string Author    { get; }
    public int Year         { get; }
    public string CoverType { get; }

    public Book (string aTitle, string anAuthor, int aYear, string aCoverType)
    {
        Title = aTitle?.Trim() 
          ?? throw new ArgumentNullException(nameof(aTitle));
        
        Author = anAuthor?.Trim() 
          ?? throw new ArgumentNullException(nameof(anAuthor));
        
        Year = aYear > 1400 && aYear <= DateTime.Now.Year   1
          ? aYear
          : new ArgumentOutOfRangeException(nameof(aYear)); 

        CoverType = aCoverType ?? "";
    }

    ...
  •  Tags:  
  • c#
  • Related