Edward Tanguay
Edward Tanguay

Reputation: 193302

Is it OK to use a public variable in C# if it is readonly?

Is there some internal difference between the C# syntactic sugar way of making properties:

public string FirstName { get; set; }

and just making public variables like this:

public string LastName;

I assume the first way is preferred and the second to be avoided. However, I often see this type of readonly property being used which is a form of the second type above:

public readonly string InternalCode;

Is this a best-practice way to create readonly property?

using System;

namespace TestProps
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer customer = new Customer();
            customer.FirstName = "Jim";
            customer.LastName = "Smith";
            customer.Show();
        }
    }

    class Customer
    {
        public string FirstName { get; set; } //prefered
        public string LastName; //avoid
        public readonly string InternalCode; //???

        public Customer()
        {
            InternalCode = "234729834723984";
        }

        public void Show()
        {
            Console.WriteLine("{0}, {1} ({2})", LastName, FirstName, InternalCode);
            Console.ReadLine();
        }
    }
}

Upvotes: 19

Views: 10587

Answers (5)

Neepsnikeep
Neepsnikeep

Reputation: 309

Short answer: public const is ok, public readonly not necessarily, public get without set not neccessarily. Objects that cannot be changed without being assigned can be ok. Reference types are dangerous as you can still change their values, even if you cannot change the reference itself.

The problem with the readonly keyword is that it does not mean what you'd understand as logically readonly/immutable. It means more like "can only be assigned in constructor". References cannot be changed, but its values can. There is no "real" readonly keyword provided by c#, unfortunately. See also https://blogs.msdn.microsoft.com/ericlippert/2007/11/13/immutability-in-c-part-one-kinds-of-immutability/

Properties cannot have the readonly keyword (https://titombo.wordpress.com/2012/11/11/using-the-c-modifiers/). As others noted, you can use a property and only define get and no set, though you cannot set that property in the constructor. Using a private set, you can set the property from annywhere in the class, not only in the constructor. The readonly field would be a little more restrictive.

Upvotes: 0

Michael Klement
Michael Klement

Reputation: 3414

Using a property provides an interface which is more resistant to change in the future. Let's say some time in the future, a decision is made to add a prefix to the internal code.

Using a public readonly variable exposes your internal structure and you will have a hard time adding the prefix to every line you used the internal variable of the class.

Using a Property, you can just write the following

public string InternalCode { 
    get { return _prefix + _internalCode; } 
}

and you're done!

Upvotes: 4

Dirk Vollmar
Dirk Vollmar

Reputation: 176169

Since he didn't answer (yet) and no one else referenced this yet: There is a great article on this topic by Jon Skeet amending his book C# in depth (give credits to Jon):

Why Properties Matter

Upvotes: 17

Luis Abreu
Luis Abreu

Reputation: 4518

In my opinion, it's ok to expose public fields (especially if they're readonly or const). Having said that, I'd say that in the example you're presenting, I'd probably go with properties since they'll give you 2 advantages (over fields): 1) better encapsulation and may let you adapt your code in the future and 2) if you're doing data binding, then you do need the properties.

Upvotes: 3

shahkalpesh
shahkalpesh

Reputation: 33476

Yes. it is OK to have a public readonly variables (it is just that they can be initialized at the time of definition or constructor).

e.g. Decimal.MaxValue

Having public readonly property is good, if the backing value changes (other than what it was initialized with).

e.g. Environment.TickCount

I thought that Environment.NewLine will be a public readonly variable. Well, it is a public property (get only) and the reason could be to maintain compatibility across different platform.

Upvotes: 1

Related Questions