Reading F# and C# these days, one of the big difference is, F# variants are by default Immutable, most C# reference types are by default mutable.
This brings to a question, how to efficiently introduce this "Immutable as by default" to C# coding? er... i mean C# 4.0..
What came to my mind is an "Immutable Attribute".
So when this is docked to a class, by Aspect, each and every member of the class is checked, so that they are only mutable in constructors.
How do you think?
The readonly keyword is a language-level construct to perform the very action you're requesting. When applied to member variables, they can only be set in the constructor and must be set in the constructor.
I'm not familiar with F#, but C# does have a readonly keyword that can only be applied to members that are initialized at object creation:
public class MyExample
{
private readonly IDependency _dependency;
public MyExample(IDependency dependency)
{
_dependency = dependency;
}
public IDependency Dependency
{
get { return _dependency; }
}
}
The keyword can only be applied to members that are immutable, meaning there's no mechanism to alter them from outside the class.
I'm not entirely sure what you're trying to accomplish -- whether you're suggesting a new feature for C# or if you're asking how to implement forcing private variables to be immutable except during construction.
If it's the latter, you could accomplish that by making your private variables readonly when you declare them. You can't make every variable you declare "read only" by default, so you'll always have to specify this keyword, but with a bit of discipline when writing new code, it'd get the job done.
One more thing to note: a variable being immutable isn't the same as the object it points to being immutable.
For example,
public class MyClass
{
private readonly List<string> myList;
public MyClass()
{
myList = new List<string>(); // okay
}
public void DoStuff()
{
myList = new List<string>(); // not okay; myList is readonly!
myList.Add("this will work"); // okay -- the list itself is still mutable
}
}
Related
I currently know of two ways to make an instance immutable in C#:
Method 1 - Compile Time Immutability
void Foo()
{
// Will be serialized as metadata and inserted
// as a literal. Only valid for compile-time constants
const int bar = 100;
}
Method 2 - Readonly Fields
class Baz
{
private readonly string frob;
public Baz()
{
// Can be set once in the constructor
// Only valid on members, not local variables
frob = "frob";
}
}
It would be nice to have a guarantee that, some instance, once instantiated, will not be changed. const and readonly do this to a small degree, but are limited in their scope. I can only use const for compile-time constants, and readonly for member variables.
Is there any way to give a local variable immutability after its initial instantiation (the way readonly works, but on a more general level)?
Scala does this with the var keyword, which declares a new immutable value, which cannot be reassigned to after it gets its initial value:
var xs = List(1,2,3,4,5) // xs is a value - cannot be reassigned to
xs = List(1,2,3,4,5,6); // will not compile
You can't prevent variables from being re-assigned in C# with the exception of fields, by as you have already mentioned using const or readonly.
You could make your own immutable version of any existing mutable type by wrapping it or if it's your own class, re-write it to be immutable but you can't achieve it for variables in a method which is what your question seems to be getting at.
F# has a few options for immutability (the 'let keyword if I'm remembering correctly) that C# doesn't so it might be worth looking at F# if you still want to leverage the power of .NET but with complete immutability.
If the wrapper is static it cannot be overwritten. This does sacrafice compile time checking on variable names and type safety.
public static class ReadOnly
{
private static readonly Dictionary<string, object> values = new Dictionary<string, object>();
public static bool SetValue(string name, object data)
{
if (values.ContainsKey(name))
return false;
values[name] = data;
return true;
}
public static object GetValue(string name)
{
return values[name];
}
}
ReadOnly.SetValue("xs", 1);
ReadOnly.SetValue("xs", 1); // will crash
I'm trying to figure out how I am able to successfully change a "readonly" array. The code below runs successfully, but I'm quite confused as to why the dereferencing of a private/readonly array is legal, as marked below:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyClass myClass = new MyClass();
myClass.Time[5] = 5; // Why is this legal? How can I make it illegal?
}
}
public class MyClass
{
private readonly uint[] time;
public IList<uint> Time
{
get { return time; }
}
public MyClass()
{
time = new uint[7];
}
}
}
As I Note above, I would expect that Time[5] would be illegal due to the fact that public IList Time does not have a setter.
How can I change MyClass to ensure that it is not legal to do myClass.Time[5] ?
Note: I've clarified the intent of this question, I was unclear at the start that the intention is to make this ILLEGAL. And I want to understand why its legal in the first place as is.
As I Note above, I would expect that
Time[5] would be illegal due to the
fact that public IList Time does not
have a setter.
The absence of a setter means that you can't assign a NEW ARRAY to the backing field of the property, but it doesn't mean that you can't change the CURRENT array reference that the backing field is pointing to.
Additionally, how can I create an
array in the constructor which is
read-only and unchangeable outside of
this class?
You can instatnitate a readonly field either at the declaration stage or in the constructor of the class as per MSDN.
As for how to fix this, the following MSDN article discuses this exact issue and some way to remedy it. I am not sure what your requirements are, but I would recommend looking into implementing a custom collection using ReadOnlyCollectionBase then passing that along or you can use ReadOnlyCollection<T>. The link to the ReadOnlyCollectionBase provides an example of an implementation.
readonly means that the field itself cannot be changed (that is, you cannot say "this.time = new uint[10]" outside the constructor). Arrays are mutable objects, so anywhere you have a reference to the array, the possessor of that reference can change the values stored in that array.
readonly fields are writable only in the constructor (this includes field initializers)
Two options for you:
Do a shallow copy of the array in the Time property, so callers can't modify your copy of the array
Use ReadOnlyCollection to prevent modifications at all
Time property hasn't setter so you will be not able to do something like this:
static void Main(string[] args)
{
MyClass myClass = new MyClass();
myClass.Time = new List<uint>();
}
but you are able to use indexer so Time[5] is legal.
Additionally, how can I create an array in the constructor which is read-only and unchangeable outside of this class?
read-only fields can be initialized in constructor only. Initialization right after declaration is the same as initialization in constructor.
I need to implement a read only property on my type. Moreover the value of this property is going to be set in the constructor and it is not going to be changed (I am writing a class that exposes custom routed UI commands for WPF but it does not matter).
I see two ways to do it:
class MyClass
{
public readonly object MyProperty = new object();
}
class MyClass
{
private readonly object my_property = new object();
public object MyProperty { get { return my_property; } }
}
With all these FxCop errors saying that I should not have public member variables, it seems that the second one is the right way to do it. Is this correct?
Is there any difference between a get only property and a read only member in this case?
The second way is the preferred option.
private readonly int MyVal = 5;
public int MyProp { get { return MyVal;} }
This will ensure that MyVal can only be assigned at initialization (it can also be set in a constructor).
As you had noted - this way you are not exposing an internal member, allowing you to change the internal implementation in the future.
C# 6.0 adds readonly auto properties
public object MyProperty { get; }
So when you don't need to support older compilers you can have a truly readonly property with code that's just as concise as a readonly field.
Versioning:
I think it doesn't make much difference if you are only interested in source compatibility.
Using a property is better for binary compatibility since you can replace it by a property which has a setter without breaking compiled code depending on your library.
Convention:
You are following the convention. In cases like this where the differences between the two possibilities are relatively minor following the convention is better. One case where it might come back to bite you is reflection based code. It might only accept properties and not fields, for example a property editor/viewer.
Serialization
Changing from field to property will probably break a lot of serializers. And AFAIK XmlSerializer does only serialize public properties and not public fields.
Using an Autoproperty
Another common Variation is using an autoproperty with a private setter. While this is short and a property it doesn't enforce the readonlyness. So I prefer the other ones.
Readonly field is selfdocumenting
There is one advantage of the field though:
It makes it clear at a glance at the public interface that it's actually immutable (barring reflection). Whereas in case of a property you can only see that you cannot change it, so you'd have to refer to the documentation or implementation.
But to be honest I use the first one quite often in application code since I'm lazy. In libraries I'm typically more thorough and follow the convention.
With the introduction of C# 6 (in VS 2015), you can now have get-only automatic properties, in which the implicit backing field is readonly (i.e. values can be assigned in the constructor but not elsewhere):
public string Name { get; }
public Customer(string name) // Constructor
{
Name = name;
}
private void SomeFunction()
{
Name = "Something Else"; // Compile-time error
}
And you can now also initialise properties (with or without a setter) inline:
public string Name { get; } = "Boris";
Referring back to the question, this gives you the advantages of option 2 (public member is a property, not a field) with the brevity of option 1.
Unfortunately, it doesn't provide a guarantee of immutability at the level of the public interface (as in #CodesInChaos's point about self-documentation), because to a consumer of the class, having no setter is indistinguishable from having a private setter.
In C# 9, Microsoft introduced a new way to have properties set only on initialization using the init accessor, like so:
public class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
This way, you can assign values when initializing a new object:
var person = new Person
{
Firstname = "John",
LastName = "Doe"
}
But later on, you cannot change it:
person.LastName = "Denver"; // throws a compiler error
You can do this:
public int Property { get { ... } private set { ... } }
I agree that the second way is preferable. The only real reason for that preference is the general preference that .NET classes not have public fields. However, if that field is readonly, I can't see how there would be any real objections other than a lack of consistency with other properties. The real difference between a readonly field and get-only property is that the readonly field provides a guarantee that its value will not change over the life of the object and a get-only property does not.
yet another way (my favorite), starting with C# 6
private readonly int MyVal = 5;
public int MyProp => MyVal;
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties#expression-body-definitions
The second method is preferred because of the encapsulation. You can certainly have the readonly field be public, but that goes against C# idioms in which you have data access occur through properties and not fields.
The reasoning behind this is that the property defines a public interface and if the backing implementation to that property changes, you don't end up breaking the rest of the code because the implementation is hidden behind an interface.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Initialize class fields in constructor or at declaration?
We are arguing about coding practices. The examples here are a little too simple, but the real deal has several constructors. In order to initialise the simple values (eg dates to their min value) I have moved the code out of the constructors and into the field definitions.
public class ConstructorExample
{
string _string = "John";
}
public class ConstructorExample2
{
string _string;
public ConstructorExample2()
{
_string = "John";
}
}
How should it be done by the book? I tend to be very case by case and so am maybe a little lax about this kind of thing. However i feel that occams razor tells me to move the initialisation out of multiple constructors. Of course, I could always move this shared initialisation into a private method.
The question is essentially ... is initialising fields where they are defined as opposed to the constructor bad in any way?
The argument I am facing is one of error handling, but i do not feel it is relevant as there are no possible exceptions that won't be picked up at compile time.
Note that all such field declaration-level initialization will be performed once for each constructor-chain, even if the constructor by itself sets the field to something else.
If you chain constructors together, the fields will be initialized in the common, first, constructor that is called.
Look at this example:
using System;
namespace ClassLibrary3
{
public class Class1
{
private string _Name = "Lasse";
public Class1()
{
}
public Class1(int i)
: this()
{
}
public Class1(bool b)
{
_Name = "Test";
}
}
}
This code compiles as this:
using System;
namespace ClassLibrary3
{
public class Class1
{
private string _Name;
public Class1()
{
_Name = "Lasse"
}
public Class1(int i)
: this()
{
// not here, as this() takes care of it
}
public Class1(bool b)
{
_Name = "Lasse"
_Name = "Test";
}
}
}
It's not necessarily bad to initialize values outside of the constructor, and the problem you have here:
string _string;
public ConstructorExample2()
{
_string = "John";
}
Is that if you have multiple constructors you have to remember to either
1. Reinitialize _string in every constructor
2. Separate the logic out into a common method and call that method in every constructor
3. Call the constructor with the logic in it, from the other constructors. (Chain the constructors)
Now this isn't necessarily a problem, but you have to remember to do it. By initializing it outside of the constructor, it's done for you. It's one less thing you need to remember to do.
Microsoft FxCop by default recommends field initializers over using the constructor. This question is also a duplicate of this one and should provide some insight.
With static classes, you'll have to note some subtleties as addressed at this question.
In the above example the assignment of "John" to _string has no logical reliance on any variables and therefore it should be outside of the constructor in the field initializer.
So long as it is not possible to initialize the object in an non-usable state then it doesn't matter.
When the code is compiled both approaches will be the same anyway.
Not sure about C#, but in Java source code they seem to prefer the constructor, example:
public class String{
char[] value;
int offset;
...
public String(){
value = new char[0];
offset = 0;
...
}
}
I think for simple initializations like that it's fine to do it in the declaration. However, I don't understand the error handling argument. Even if there is an exception in the initialization, I think you will find that your normal error handling mechanism will work the same. It will still throw an exception when you call the constructor.
I tend to initialize things in the get accessor, where they are first used. If null then initialize and all that.
I prefer to initialize simple fields like that outside of the constructor.
It shouldn't cause any issues since compilation actually moves those initializations into the constructor at compile-time anyway.
If the initialization of the variable will be the same, no matter what arguments are passed to the constructor, then it doesn't make sense to clutter the constructor method with the unnecessary initialization code. In this case, I initialize in-place.
Inisialing the fields in the constructor is better. This way if/when a different constructor is added you know that all the fields are starting with null/default values and you can initialise them appropriately.
Sometimes you have a private field that backs a property, you only ever want to set the field via the property setter so that additional processing can be done whenever the field changes. The problem is that it's still easy to accidentally bypass the property setter from within other methods of the same class and not notice that you've done so. Is there a way in C# to work around this or a general design principle to avoid it?
IMHO, it is not used, because:
The class must trust itself
If your class gets as large that one part does not know the other, it should be divided.
If the logic behind the property is slightly more complex, consider to encapsulate it in an own type.
I'd consider this a nasty hack and try to avoid it if possible, but...
You can mark the backing field as obsolete so that the compiler will generate a warning when you try to access it, and then suppress that warning for the property getter/setter.
The warning codes that you'd need to suppress are CS0612 for the plain Obsolete attribute and CS0618 if the attribute has a custom message.
[Obsolete("Please don't touch the backing field!")]
private int _backingField;
public int YourProperty
{
#pragma warning disable 612, 618
get { return _backingField; }
set { _backingField = value; }
#pragma warning restore 612, 618
}
There's no inbuilt way to do what you want to do, but by the sounds of things you need another layer of abstraction between your class and that value.
Create a separate class and put the item in there, then your outer class contains the new class, and you can only access it through its properties.
No, there isn't. I'd quite like this myself - something along the lines of:
public string Name
{
private string name; // Only accessible within the property
get { return name; /* Extra processing here */ }
set { name = value; /* Extra processing here */ }
}
I think I first suggested this about 5 years ago on the C# newsgroups... I don't expect to ever see it happen though.
There are various wrinkles to consider around serialization etc, but I still think it would be nice. I'd rather have automatically implemented readonly properties first though...
You CAN do this, by using a closure over a local in the constructor (or other initialisation function). But it requires significantly more work that the helper class approach.
class MyClass {
private Func<Foo> reallyPrivateFieldGetter;
private Action<Foo> reallyPrivateFieldSetter;
private Foo ReallyPrivateBackingFieldProperty {
get { return reallyPrivateFieldGetter(); }
set { reallyPrivateFieldSetter(value); }
}
public MyClass() {
Foo reallyPrivateField = 0;
reallyPrivateFieldGetter = () => { return reallyPrivateField; }
reallyPrivateFieldSetter = v => { reallyPrivateField = v; };
}
}
I suspect that the underlying field type Foo will need to be a reference class, so the two closures are created over the same object.
There is no such provisioning in C#.
However I would name private variables differently (e.g. m_something or just _something) so it is easier to spot it when it is used.
You can put all of your private fields into a nested class and expose them via public properties. Then within your class, you instantiate that nested class and use it. This way those private fields are not accessible as they would have been if they were part of your main class.
public class A
{
class FieldsForA
{
private int number;
public int Number
{
get
{
//TODO: Extra logic.
return number;
}
set
{
//TODO: Extra logic.
number = value;
}
}
}
FieldsForA fields = new FieldsForA();
public int Number
{
get{ return fields.Number;}
set{ fields.Number = value;}
}
}
It just provides a level of obstruction. The underlying problem of accessing private backing fields is still there within the nested class. However, the code within class A can't access those private fields of nested class FieldForA. It has to go through the public properties.
Perhaps a property backing store, similar to the way WPF stores properties?
So, you could have:
Dictionary<string,object> mPropertyBackingStore = new Dictionary<string,object> ();
public PropertyThing MyPropertyThing
{
get { return mPropertyBackingStore["MyPropertyThing"] as PropertyThing; }
set { mPropertyBackingStore["MyPropertyThing"] = value; }
}
You can do all the pre-processing you want now, safe in the knowledge that if anyone did access the variable directly, it would have been really really hard compared to the property accessor.
P.S. You may even be able to use the dependency property infrastructure from WPF...
P.P.S. This is obviously going to incur the cost of casting, but it depends on your needs - if performance is critical, perhaps this isn't the solution for you.
P.P.P.S Don't forget to initialise the backing store! (;
EDIT:
In fact, if you change the value property stored to a property storage object (using the Command pattern for example), you could do your processing in the command object...just a thought.
Can't do this in standard C#, however you could
define a custom attribute say OnlyAccessFromProperty
write your code like
[OnlyAccessFromProperty(Name)]
String name
Name
{
get{return name;}
}
etc …
Then write a custom rule for FxCop (or another checker)
Add FxCop to your build system so if your custom rule find an error the build is failed.
Do we need a set of standard custom rules/attributes to enforce common design patens like this without the need to extend C#
C# has no language feature for this. However, you can rely on naming conventions, similar to languages which have no private properties at all. Prefix your more private variable names with _p_, and you'll be pretty sure that you don't type it accidentally.
I don't know C# but in Java you may have a base class with only private instance variables and public setters and getters (should return a copy of the instance var.) and do all other in an inherited class.
A "general design principle" would be "use inheritance".
There is no build in solution in C#, but I think your problem can be solved by good OO design:
Each class should have a single purpose. So try to extract the logic around your field into a class as small as possible. This reduces the code where you can access the field by accident. If you do such errors by accident, your class is probably to big.
Often interface are good to restrict access to only a certain "subset" of an object. If that's appropriate for your case depends on your setting of course. More details about the work to be done would help to provide a better answer.
You say that you do additional processing. Presumably this would be detectable under the correct conditions. My solution, then, would be to create unit tests that implement conditions such that if the backing field is used directly the test will fail. Using these tests you should be able to ensure that your code correctly uses the property interface as long as the tests pass.
This has the benefit that you don't need to compromise your design. You get the safety of the unit tests to ensure that you don't accidently make breaking changes and you capture the understanding of how the class works so that others who come along later can read your tests as "documentation."
Wrap it in a class? The property thing is a bit like that anyway, associating data with methods - the "Encapsulation" they used to rave about...
class MyInt
{
private int n;
public static implicit operator MyInt(int v) // Set
{
MyInt tmp = new MyInt();
tmp.n = v;
return tmp;
}
public static implicit operator int(MyInt v) // Get
{
return v.n;
}
}
class MyClass
{
private MyInt myint;
public void func()
{
myint = 5;
myint.n = 2; // Can't do this.
myint = myint + 5 * 4; // Works just like an int.
}
}
I'm sure I'm missing something? It seems too normal...
BTW I do like the closures one, superbly mad.
My favorite solution to this (and what I follow) is to name private backing fields that are never intended to be used directly with a leading underscore, and private fields that are intended to be used without the underscore (but still lowercase).
I hate typing the underscore, so if I ever start to access a variable that starts with the underscore, I know somethings wrong - I'm not supposed to be directly accessing that variable. Obviously, this approach still doesn't ultimately stop you from accessing that field, but as you can see from the other answers, any approach that does is a work around and/or hardly practical.
Another benefit of using the underscore notation is that when you use the dropdown box to browse your class, it puts all of your private, never-to-be-used backing fields all in one place at the top of the list, instead of allowing them to be mixed in with their respective properties.
As a design practice, you could use a naming convention for "private properties" that's different from normal public members - for instance, using m_ItemName for private items instead of ItemName for public ones.
If you're using the C# 3.0 compiler you can define properties which have compiler-generated backing fields like this:
public int MyInt { get; set; }
That will mean there is only one way to access the property, sure it doesn't mean you can only access the field but it does mean that there's nothing but the property to access.
I agree with the general rule that the class should trust itself (and by inference anybody coding within the class).
It is a shame that the field is exposed via intellisense.
Sadly placing [EditorBrowsable(EditorBrowsableState.Never)] does not work within that class (or indeed the assembly(1))
In Visual C#, EditorBrowsableAttribute does not suppress members from a class in the same assembly.
If you really do wish to solve this aspect of it the the following class may be useful and makes the intent clear as well.
public sealed class TriggerField<T>
{
private T data;
///<summary>raised *after* the value changes, (old, new)</summary>
public event Action<T,T> OnSet;
public TriggerField() { }
///<summary>the initial value does NOT trigger the onSet</summary>
public TriggerField(T initial) { this.data=initial; }
public TriggerField(Action<T,T> onSet) { this.OnSet += onSet; }
///<summary>the initial value does NOT trigger the onSet</summary>
public TriggerField(Action<T,T> onSet, T initial) : this(onSet)
{
this.data=initial;
}
public T Value
{
get { return this.data;}
set
{
var old = this.data;
this.data = value;
if (this.OnSet != null)
this.OnSet(old, value);
}
}
}
Allowing you to (somewhat verbosely) use it like so:
public class Foo
{
private readonly TriggerField<string> flibble = new TriggerField<string>();
private int versionCount = 0;
public Foo()
{
flibble.OnSet += (old,current) => this.versionCount++;
}
public string Flibble
{
get { return this.flibble.Value; }
set { this.flibble.Value = value; }
}
}
alternatively you can go for a less verbose option but accessing Flibble is by the not idiomatic bar.Flibble.Value = "x"; which would be problematic in reflective scenarios
public class Bar
{
public readonly TriggerField<string> Flibble;
private int versionCount = 0;
public Bar()
{
Flibble = new TriggerField<string>((old,current) => this.versionCount++);
}
}
or solution if you look at the community content!
The new Lazy class in .net 4.0
provides support for several common
patterns of lazy initialization
In my experience this is the most common reason I wish to wrap a field in a private properly, so solves a common case nicely. (If you are not using .Net 4 yet you can just create your own “Lazy” class with the same API as the .Net 4 version.)
See this and this and this for details of using the Lazy class.
Use the "veryprivate" construct type
Example:
veryprivate void YourMethod()
{
// code here
}