I have a .Net C# class where I need to make a variable public. I need to initialize this variable within a method (not within the constructor). However, I don't want the variable to be modifieable by other classes. Is this possible?
-
7And the award for quickest question to 5 answers goes to... – 3Dave Jan 11 '11 at 20:22
9 Answers
Don't use a field - use a property:
class Foo
{
public string Bar { get; private set; }
}
In this example Foo.Bar
is readable everywhere and writable only by members of Foo
itself.
As a side note, this example is using a C# feature introduced in version 3 called automatically implemented properties. This is syntactical sugar that the compiler will transform into a regular property that has a private backing field like this:
class Foo
{
[CompilerGenerated]
private string <Bar>k__BackingField;
public string Bar
{
[CompilerGenerated]
get
{
return this.<Bar>k__BackingField;
}
[CompilerGenerated]
private set
{
this.<Bar>k__BackingField = value;
}
}
}

- 344,730
- 71
- 640
- 635
-
4But what if it is a reference type instead of a value type? Couldn't another class read the reference and then modify properties of the object that it points to? – JoeMjr2 Mar 14 '16 at 19:42
-
They can. For instance even in this case List's `Add` can be called, if List is a member. I had to deal with it with List (of course it is only one use-case of a reference) and ended-up doing ReadOnlyCollection member with getter only and private variable - a list. – Do-do-new Nov 05 '18 at 16:12
You have to use a property for this. If you are fine with an automatic getter/setter implementation, this will work:
public string SomeProperty { get; private set; }
Note that you should not expose fields as public anyway, except in some limited circumstances. Use a property instead.

- 158,093
- 24
- 286
- 300
Sure. Make it a property, and make the setter private:
public Int32 SomeVariable { get; private set; }
Then to set it (from within some method in the class):
SomeVariable = 5;

- 26,726
- 31
- 139
- 202

- 50,833
- 6
- 93
- 125
Use a private variable and expose a public property.
class Person
{
private string name;
public string Name
{
get
{
return name;
}
}
}

- 3,714
- 1
- 18
- 20
Necro for sure, but this bares mentioning with the improvements to the language in 6.0
class Foo {
// The new assignment constructor is wonderful shorthand ensuring
// that the var is only writable inside the obj's constructor
public string Bar { get; private set; } = String.Empty;
}

- 432
- 3
- 14
-
This won't work inside a method because it will be a read-only property. – usefulBee May 23 '17 at 15:32
The answers so far work good as long as you dont use reference types. Otherwise you will still be able to manipulate the internals of that variable. e.g:
using System;
namespace Playground
{
class Program
{
static void Main(string[] args)
{
var fo = new Fo();
fo.Init();
Console.WriteLine(fo.SomeBar.SomeValue);
fo.SomeBar.SomeValue = "Changed it!";
Console.WriteLine(fo.SomeBar.SomeValue);
Console.Read();
}
public class Fo
{
public Bar SomeBar { get; private set; }
public void Init()
{
SomeBar = new Bar{SomeValue = "Hello World!"};
}
}
public class Bar
{
public String SomeValue { get; set; }
}
}
}
This will result in the console output:
Hello World!
Changed it!
Which may be exactly what you want as you wont be able to change SomeBar but if you want to make the internals of the variable unmodifiable you need to pass back a copy of the variable, e.g.:
using System;
namespace Playground
{
class Program
{
static void Main(string[] args)
{
var fo = new Fo();
fo.Init();
Console.WriteLine(fo.SomeBar.SomeValue);
fo.SomeBar.SomeValue = "Changed it!";
Console.WriteLine(fo.SomeBar.SomeValue);
Console.Read();
}
public class Fo
{
private Bar _someHiddenBar;
public Bar SomeBar => new Bar(_someHiddenBar);
public void Init()
{
_someHiddenBar = new Bar{SomeValue = "Hello World!"};
}
}
public class Bar
{
public String SomeValue { get; set; }
public Bar(){}
public Bar(Bar previousBar)
{
SomeValue = previousBar.SomeValue;
}
}
}
}
which will result in the output:
Hello World!
Hello World!
See comments for why I added the third example:
using System;
namespace Playground
{
class Program
{
static void Main(string[] args)
{
var fo = new Fo();
fo.Init();
Console.WriteLine(fo.SomeBar.SomeValue);
//compile error
fo.SomeBar.SomeValue = "Changed it!";
Console.WriteLine(fo.SomeBar.SomeValue);
Console.Read();
}
public class Fo
{
private Bar _someHiddenBar;
public Bar SomeBar => new Bar(_someHiddenBar);
public void Init()
{
_someHiddenBar = new Bar("Hello World!");
}
}
public class Bar
{
public String SomeValue { get; }
public Bar(string someValue)
{
SomeValue = someValue;
}
public Bar(Bar previousBar)
{
SomeValue = previousBar.SomeValue;
}
}
}
}

- 387
- 3
- 7
-
This doesn't look good. You're calling `fo.SomeBar.SomeValue = "Changed it!";` which does not do the assignment nor does it exception. If this was real code, it'd be a nightmare to debug. You should make things immutable so that you can't even compile _or_ you should throw an exception. – rbm Aug 08 '17 at 08:18
-
This is a good point. How would you change it, so that *SomeValue* can still be changed by his owner but not by reference? – kkCosmo Aug 08 '17 at 08:32
-
Look at the other answers, `private set;` is the most common way. Your example has effectively two classes, so you'd need to control the `Fo.Bar` and the `Bar.SomeValue` and make them immutable. – rbm Aug 08 '17 at 08:39
-
But that is beside the point. JoeMjr2 pointed out (in the comment of the top answer) that that works for value types, but that you still could modify the variables of a reference type. Hence my example with two classes. Making `SomeValue` private would not allow `Fo` the modification MikeTWebb asked for. – kkCosmo Aug 08 '17 at 08:45
-
1
-
Depending on the needs of 'Fo' and the complexity of 'Bar' this has benefits. I agree. In that case the constructor of 'Bar' would take the value for 'SomeValue' and 'SomeValue' would be defined with e.g. a private setter. I will add it as third example. – kkCosmo Aug 08 '17 at 08:56
Are you not allowed to use a property for this? If you are:
private string _variable
public string Variable {
get {
return _variable;
}
}

- 8,277
- 3
- 33
- 49
Define it as private? Is that what you asking for, you can modify it any where inside the container class but you can't out side it

- 7,015
- 12
- 47
- 75