I have some information, which is not changed during execution program. It is sort of static information. I am using following code:
public class Foo
{
public static readonly List<int> = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
};
Unfortunately during execution of program, I can change fields of such static member. As result I have the following warning:
"Do not declare read only mutable reference types".
What is best practise to cope with this problem?
In C#, it's not possible to make the members of someone else's class immutable. I'm guessing your familiar with the C++ concept of a const reference, but C# does not have anything like that.
If you want to control access, I'd make the typeface private, and add read-only static properties and methods to Foo. This means you could get read-only access like;
Foo.TypeFaceSize;
Foo.TypeFaceName;
The C# compiler can only enforce readonly access to a property or a field. If you make a field readonly, the settable properties of the object in this field are still settable and the only way to change that is to modify the class definition of the object.
You could possibly wrap the object in your own custom class and allow only getters. But you may need to have several layers of wrappers, so I would suggest not doing it and just paying attention to compiler warnings.
You can't turn a mutable type into an immutable type in C# as is.
If you want to expose TypeFace like an immutable type you could wrap it with a type that has the same properties but it exposes them as read-only properties:
public class A
{
public string Text { get; set; }
}
public class AReadOnly
{
public AReadOnly(A a)
{
A = a;
}
private A A { get; }
public string Text => A.Text;
}
public class B
{
public B()
{
A = new AReadOnly(_A);
}
private A _A { get; } = new A();
public AReadOnly A { get; }
}
Related
I have a class called Package, in this class I have around 10 attributes, let's call them 1,2,3,4.. etc to 10. The types of these attributes are strings, ints and some DateTimes. When making a new object of Package sometimes I just need attribute 1, sometimes I need 5, 6 and 9, and sometimes I need 3 and 10 etc.
So just two examples: new Package("bla", "bla bla",100) or new Package(2983)
I've read:
An interface looks like a class, but has no implementation. The only
thing it contains are declarations of events, indexers, methods and/or
properties. The reason interfaces only provide declarations is because
they are inherited by classes and structs, which must provide an
implementation for each interface member declared.
Since there are no other methods in the class and just a constructor and attributes, is it better to use like 20 constructors or should I make an interface for this situation?
EDIT:
I should've probably mentioned that I also have some enums to 'kind of' determine what kind of Package it is.
An interface doesn't help you in any way here.
If you want to force that specific variables are filled in together, like 1, 2 and 3 should always be filled together but in another case just 4 is enough, you could use separate constructors, or static methods with helpful names that create the objects (like CreateFromId, CreateFromNameAndAge).
If you don't care at all, you can simply make a parameterless constructor (or a constructor with optional fields) and set the fields required with object initializers:
var x = new Class() { Field1 = 1, Field2 = "2" };
Maybe this is a sign you are doing too much in a single object, but without actual information about your class design, we can't tell that much.
Inheritance seems to be a decent solution here too, if the packages have distinct uses (like ProductPackage, PersonPackage, etc.). The shared properties reside in the base class, and all specific properties can reside in the deriving classes.
Constructors provide guidelines as to how can an object be created. Assuming that by using an interface you mean specify the properties which need to exist, you are not giving any guidelines as to how properties need to be initialized.
Having multiple constructors should be better since you are providing means in which users can instantiate your objects. This will allow you to initialize your other parameters accordingly.
You could still use an interface if you require to stipulate what fields need to exist.
Besides above points, consider using Builder pattern - https://en.wikipedia.org/wiki/Builder_pattern
Here is the example:
class Package
{
public string Name { get; set; }
public string Description { get; set; }
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public static PackageBuilder Create()
{
return new PackageBuilder(new Package());
}
}
class PackageBuilder
{
private readonly Package _package;
public PackageBuilder(Package package)
{
_package = package;
}
public PackageBuilder WithName(string name)
{
_package.Name = name;
return this;
}
public PackageBuilder WithDescription(string description)
{
_package.Description = description;
return this;
}
public PackageBuilder Prop1(string prop)
{
_package.Prop1 = prop;
return this;
}
public PackageBuilder Prop2(string prop)
{
_package.Prop2 = prop;
return this;
}
public static implicit operator Package(PackageBuilder pb)
{
return pb._package;
}
}
class Client
{
Package BuildPackage()
{
var package =
Package.Create().WithName("My Package").WithDescription("Description").Prop1("foo").Prop2("bar");
return package;
}
}
I'm trying using ReadOnlyCollection to make object immutable, I want the property of object are immutable.
public ReadOnlyCollection<FooObject> MyReadOnlyList
{
get
{
return new ReadOnlyCollection<FooObject>(_myDataList);
}
}
But I little confused.
I tried to change the property of the object in to MyReadOnlyList using a foreach and ... I can change value property, is it correct? I understood ReadOnlyCollection set an add level to make the object immutable.
The fact that ReadOnlyCollection is immutable means that the collection cannot be modified, i.e. no objects can be added or removed from the collection. This does not mean that the objects it contains immutable.
This article by Eric Lippert, explains how different kinds of immutability work. Basically, a ReadOnlyCollection is an immutable facade which can read the underlying collection (_myDataList), but cannot modify it. However, you can still change the underlying collection since you have a reference to _myDataList by doing something like _myDataList[0] = null.
Furthermore, the objects returned by ReadOnlyCollection are the same ones returned by _myDataList, i.e. this._myDataList.First() == this.MyReadOnlyList.First() (with LINQ). This means that if an object in _myDataList is mutable, then so is the object in MyReadOnlyList.
If you want the objects to be immutable, you should design them accordingly. For instance, you might use:
public struct Point
{
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
// In C#6, the "private set;" can be removed
public int X { get; private set; }
public int Y { get; private set; }
}
instead of:
public struct Point
{
public int X { get; set; }
public int Y { get; set; }
}
Edit: in this case, as noted by Ian Goldby, neither struct allows you to modify properties of the elements in the collection. This happens because structs are value types and when you access an element the collection returns a copy of the value. You can only modify the properties of a Point type if it is a class, which would mean that references to the actual objects are returned, instead of copies of their values.
I tried to change the property of the object in to MyReadOnlyList
using a foreach and ... I can change value property, is it correct? I
understood ReadOnlyCollection set an add level to make the object
immutable.
Using a ReadOnlyCollection does not make any guarantees as for the object that is stored in the collection. All it guarantees is that the collection cannot be modified once it has been created. If an element is retrieved from it, and it has mutable properties, it can very well be modified.
If you want to make your FooObject an immutable one, then simply do so:
public class FooObject
{
public FooObject(string someString, int someInt)
{
SomeString = someString;
SomeInt = someInt;
}
public string SomeString { get; };
public int SomeInt { get; };
}
What is immutable is the collection itself, not the objects. For now, C# doesn't support immutable objects without wrapping them as ReadOnlyCollection<T> does in your case.
Well, you can still create immutable objects if their properties have no accessible setter. BTW, they're not immutable at all because they can mutate from a class member that may have equal or more accessibility than the setter.
// Case 1
public class A
{
public string Name { get; private set; }
public void DoStuff()
{
Name = "Whatever";
}
}
// Case 2
public class A
{
// This property will be settable unless the code accessing it
// lives outside the assembly where A is contained...
public string Name { get; internal set; }
}
// Case 3
public class A
{
// This property will be settable in derived classes...
public string Name { get; protected set; }
}
// Case 4: readonly fields is the nearest way to design an immutable object
public class A
{
public readonly string Text = "Hello world";
}
As I said before, reference types are always mutable by definition and they can behave as immutable under certain conditions playing with member accessibility.
Finally, structs are immutable but they're value types and they shouldn't be used just because they can represent immutable data. See this Q&A to learn more about why structs are immutable: Why are C# structs immutable?
What is the best practice to create pre-initialized class. For example
Chip chip = new Atmega8();
I would like to have its properties already defined like:
chip.Name = "Atmega8 AVR Chip";
and so on.
How to achieve it in C#?
Should I use readonly public properties or property with private set?
Have your constructor initialize the values:
class Atmega8 {
public Atmega8 ()
{
Name = "Atmega8 AVR Chip";
}
public string Name { get; set; }
}
If you intend Name to be the same for all instances, it might make sense to declare it abstract in the base class and override the getter:
abstract class Chip {
public abstract string Name { get; }
}
class Atmega8 : Chip {
public override string Name {
get { return "Atmega8 AVR Chip"; }
}
}
Because we haven't defined a set method, the value cannot be changed, much like a readonly variable except it isn't even stored anywhere and just returned on each call.
If you want the compiler to enforce that nothing can change the value of the field once initialized, then set it up as a read-only field, and populate it in the constructor of the class (or simply initialize it when you declare it; this doesn't work so well with inheritance though). If you don't care as long as nothing OUTSIDE the object can change it (meaning you will trust your own coding discipline to ensure it doesn't change internally), a get-only property with a backing field, or an auto-property with a private setter, are your bets.
IF you absitively posolutely DO NOT WANT the value to change for a particular class, EVER, then I would make it a get-only property returning either a string literal or a constant. I would recommend using the constant over the literal, as you can put the constants into their own static class which you can then use separately from each Chip class.
HOWEVER, there's a quirk of constants you should know. A constant value in .NET is stored in the manifest of not only the assembly containing the declaring code, but in every assembly that references the declaring assembly. Each assembly's code them uses the value from its own manifest. So, if the constant value EVER changes, any assembly that references the declaring assembly must be recompiled to update those assemblies' manifests with the new value. Otherwise, the constant will only have its new value when used from within the declaring assembly. For this reason, labeling a variable as constant should not be done lightly. Personally, my opinion is if the constant isn't some value on which the continued existence and functioning of the universe depends, like pi, e, the speed of light in a vacuum, Plank's Constant, Avogadro's Number, etc, then it isn't "constant". Anything else, like communication code ordinals, CAN change, even if doing so would break compatibility with every previous version of your program.
Depends what you want to accomplish.
It looks like you never want the value of Name to change. One approach would be to declare Name as abstract in Chip, and implement Name in each child class to return a constant string value.
abstract class Chip
{
public abstract string Name { get; }
}
class Amiga8 : Chip
{
public override string Name { get { return "Atmega8 AVR Chip"; } }
}
class Program
{
static void Main(string[] args)
{
Chip chip = new Amiga8();
Console.WriteLine(chip.Name);
}
}
In the constructor of the Atmega8 class you can set a property to something. Ie:
public Atmega8() {
Name = "Atmega8 AVR Chip";
}
If you do not want that to be changed in runtime you could mark the property as readonly ( only assignable through a constructor of declarative ).
private readonly string _Name = string.Empty;
public string Name {
get { return _name; }
}
public Atmega8() {
_Name = "Atmega8 AVR Chip";
}
Value of property cannot change -> Read-only public property.
Value of property can change -> Property with private set
If you don't want it to change, make the Name property a const or readonly on the Atmega8 class. Private set still allows the Name to change internally.
You're saying that you want the class to be populated at the same time it's initialized? Just populate the object in the constructor, like so:
class Test
{
public Test()
{
this.Name = "Hello World";
}
//if you need to pass information into the constructor:
public Test(string testName)
{
this.Name = testName;
}
}
Then, you can do this to initialize it:
Test test = new Test(); //default name of Hello World!
OR
Test test = new Test("Bingo!");
I have read in many places that exposing fields publicly is not a good idea, because if you later want to change to properties, you will have to recompile all the code which uses your class.
However, in the case of immutable classes, I don't see why you would ever need to change to properties - you're not going to be adding logic to the 'set' after all.
Any thoughts on this, am I missing something?
Example of the difference, for those who read code more easily than text :)
//Immutable Tuple using public readonly fields
public class Tuple<T1,T2>
{
public readonly T1 Item1;
public readonly T2 Item2;
public Tuple(T1 item1, T2 item2)
{
Item1 = item1;
Item2 = item2;
}
}
//Immutable Tuple using public properties and private readonly fields
public class Tuple<T1,T2>
{
private readonly T1 _Item1;
private readonly T2 _Item2;
public Tuple(T1 item1, T2 item2)
{
_Item1 = item1;
_Item2 = item2;
}
public T1 Item1 { get { return _Item1; } }
public T2 Item2 { get { return _Item2; } }
}
Of course, you could use auto-properties (public T1 Item1 { get; private set; }), but this only gets you 'agreed immutability' as opposed to 'guaranteed immutability'...
C# 6.0 now supports auto-property initializers.
The auto-property initializer allows assignment of properties directly
within their declaration. For read-only properties, it takes care of
all the ceremony required to ensure the property is immutable.
You can initialize read-only properties in constructor or using auto-initializer
public class Customer
{
public Customer3(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public string FirstName { get; }
public string LastName { get; }
public string Company { get; } = "Microsoft";
}
var customer = new Customer("Bill", "Gates");
You can read more about auto-property initializers here
It is an obvious omission from properties that you cannot write something like:
public T2 Item2 { get; readonly set; }
I'm not even sure readonly is the best word to use to mean "can only be set in the constructor", but that's what we're stuck with.
This is actually a feature that many people have requested, so let's hope that it will be introduced in a hypothetical new version of C# some time soon.
See this related question.
You may not need to add any logic to a setter in the future, but you may need to add logic to a getter.
That's a good-enough reason enough for me to use properties rather than exposing fields.
If I'm feeling rigorous then I'd go for full immutability (explicit readonly backing fields with exposed getters and no setters). If I'm feeling lazy then I'd probably go for "agreed immutability" (auto-properties with exposed getters and private setters).
In C#9 we have the init accessor which you could use instead of the set accessor.
var firstCar = new Car { Color = "Orange", Brand = "Mclaren" };
public class Car
{
public string Color { get; init; }
public string Brand { get; init; }
}
An init only property (or indexer) is declared by using the init
accessor in place of the set accessor
An instance property containing an init accessor is considered
settable in the following circumstances, except when in a local
function or lambda:
During an object initializer
During a with expression initializer
Inside an instance constructor of the containing or derived type, on
this or base
Inside the init accessor of any property, on this or base
Inside attribute usages with named parameters
Init only setters
As a standard practice I follow your 2nd example only using 'readonly' when the object is public or vulnerable to inadvertent tampering. I am using the 'agreed immutability' model in a current project building a plugin framework. Obviously, with agreed immutability, the readonly protection is removed.
Only in rare circumstances do I expose a field - public, internal, or otherwise. It just doesn't feel right unless writing a property {get;} takes more time than I'm willing to give.
The idea behind properties is that, even if you don't intend to chang them now or later, mabye you might need to in some unforseen way. Let's say you need to change the getter to do some kind of calculation, or logging. Maybe you need to add exception handling. Lots of potential reasons.
Also consider semantics. if T1 is a value type rather than a reference type, then accessing obj.Item1 returns a copy of _Item1 in the getter, while accessing Item1 without a getter would not retrieve a copy. This means that while Item1 may be immutable internally, the returned value type object isn't. I can't think of a reason why that would be a good thing, but it is a difference.
Given a struct like this:
public struct SomeStruct
{
public SomeStruct(String stringProperty, Int32 intProperty)
{
this.StringProperty = stringProperty;
this.IntProperty = intProperty;
}
public String StringProperty { get; set; }
public Int32 IntProperty { get; set; }
}
Of course, a compiler error is generated that reads The 'this' object cannot be used before all of its fields are assigned to.
Is there a way to assign values to the backing fields or the properties themselves, or do I have to implement properties the old-fashioned way with my own explicit backing fields?
Prior to C# 6, you need to use the "this" constructor in this scenario:
public SomeStruct(String stringProperty, Int32 intProperty) : this()
{
this.StringProperty = stringProperty;
this.IntProperty = intProperty;
}
Doing this calls the default constructor and by doing so, it initializes all the fields, thus allowing this to be referenced in the custom constructor.
Edit: until C# 6, when this started being legal; however, these days it would be much better as a readonly struct:
public readonly struct SomeStruct
{
public SomeStruct(string stringProperty, int intProperty)
{
this.StringProperty = stringProperty;
this.IntProperty = intProperty;
}
public string StringProperty { get; }
public int IntProperty { get; }
}
If a structure is going to have, and its users will expect it to have, all three of the following characteristics:
Its entire state is encapsulated in some particular fixed set of readable members
An instance may be readily created in which those members have any combination of values which are valid for their respective types.
A default instance of the type should have all of those members set to the default values of their respective types.
the type should expose its members as fields. The above requirements mean a struct won't be able to do anything an exposed-field struct can't do, and will also mean that if code doesn't hit any threading hazards the struct will be able to do anything an exposed-field struct can do, albeit perhaps more slowly and with more threading hazards.
If a struct Foo has fields f1 and f2, and a constructor which sets those fields in that order, and if fooExpr is some sort of expression of type Foo [perhaps a variable, field, array reference, property, or whatever] the statement:
myFoo.f2 = someValue;
will only be allowed in cases where one could legally say
myFoo = new Foo(myFoo.f1, someValue);
and in all circumstances where the first form is allowed and the behavior of the second form has defined semantics, they will behave identically. Thus, trying to "encapsulate" the properties of Foo doesn't really accomplish anything except make the code more cumbersome to write, less clear, and slower to execute.