Object read only when accessed through/as another object's field - c#

Situation:
I often run into this problematic and never know how to solve it. Though I don't know where and how to look for answer.
So here it is. When you store some objects into other objects you can have them as readonly, or just with a getter, which is the same. This way you cannot change the value of a MyInt in
public class ClassA {
public readonly int MyInt;
public string MyString;
}
and no problem if I want to put this in a container as follows:
public class ClassB {
public readonly ClassA MyClassA;
public string MyString;
}
This will still work as expected. MyInt is readonly and MyStringA is not.
Problem:
But I can still get MyClassA and set MyClassA.MyStringA.
Is there a way to have a "stricter" readonly system?
With the above example I would like MyClassA's fields to be all readonly if MyClassA is.
The only solution I can think of is to have another class MyClassAreadonly. But that seems ugly and not not convenient.
Context:
The reason why I am looking for this behavior is that I want MyClassB.MyString to add logic (like firing an event) before setting MyClassB.MyClassA.MyString. So another solution is to simply not show ClassB.MyClassA by setting it as private. But that is nice to being able to retrieve MyClassA! But if I retrieve it and modify it I miss the ClassB logic!
PS: Despite I can't figure it out, I hope to have been clear enough.

You can wrap properties of ClassA into properties of ClassB like this:
public class ClassB
{
private readonly ClassA _myClassA = new ClassA();
private string _myString;
public string MyString
{
get
{
// your logic here
return _myString;
}
set
{
// your logic here
_myString = value;
}
}
public string MyStringA { get { return _myClassA.MyString;}}
public int MyIntA { get { return _myClassA.MyInt; }}
}

How about adding an event to ClassA that ClassB can then handle in order to implement the additional logic?
public class ClassA
{
public readonly int MyInt;
private string _myString;
public string MyString
{
get
{
return _myString;
}
set
{
_myString = value;
if (MyStringChanged != null)
{
MyStringChanged(this, new EventArgs());
}
}
}
public event EventHandler MyStringChanged;
}
public class ClassB
{
public readonly ClassA MyClassA;
//It sounds like you wanted to use ClassB.MyString to manipulate ClassA.MyString, so you probably won't need this anymore?
//public string MyString;
public ClassB()
{
MyClassA = new ClassA();
MyClassA.MyStringChanged += new EventHandler(MyClassA_MyStringChanged);
}
private void MyClassA_MyStringChanged(object sender, EventArgs e)
{
//Add your logic here
}
}

"Deep" immutability
As stated in a comment by #Damien_The_Unbeliever, here is a perfect "answer" to my question. I put answer between quote marks because there is no built-in solution for the moment in C#.
The closest alternative to address my issue will be to have an Immutable facade for the objects (MyClassA) I want to use this way.
Thanks Damien.
Another read on the subject: http://www.bluebytesoftware.com/blog/2007/11/11/ImmutableTypesForC.aspx

Related

Is there an easy way to make an immutable version of a class?

Is there an easy way to make an instance immutable?
Let's do an example, I have a class holding a lots of data fields (only data, no behavior):
class MyObject
{
// lots of fields painful to initialize all at once
// so we make fields mutable :
public String Title { get; set; }
public String Author { get; set; }
// ...
}
Example of creation:
MyObject CreationExample(String someParameters)
{
var obj = new MyObject
{
Title = "foo"
// lots of fields initialization
};
// even more fields initialization
obj.Author = "bar";
return obj;
}
But now that I have fully created my object, I don't want the object to be mutable anymore (because the data consumer will never need to change the state), so I would like something like that List.AsReadOnly:
var immutableObj = obj.AsReadOnly();
But if I want this behavior, I need to make another class that have exactly the same fields but without setter.
So is there any automatic way to generate this immutable class ? Or another way to allow mutability during creation but immutable once initialized ?
I know that fields can be marked as "readonly", but the object will be initialized outside of the class, and passing all fields as constructor parameters seems like a bad idea (too much parameters).
No, there is no easy way to make any type immutable, especially not if you want "deep" immutability (i.e. where no mutable object can be reached through the immutable object). You will have to explicitly design your types to be immutable. The usual mechanisms to make types immutable are these:
Declare (property-backing) fields readonly. (Or, starting with C# 6 / Visual Studio 2015, use read-only auto-implemented properties.)
Don't expose property setters, only getters.
In order to initialize (property-backing) fields, you must initialize them in the constructor. Therefore, pass the (property) values to the constructor.
Don't expose mutable objects, such as collections based on mutable-by-default types (like T[], List<T>, Dictionary<TKey,TValue>, etc.).
If you need to expose collections, either return them in a wrapper that prevents modification (e.g. .AsReadOnly()), or at the very least return a fresh copy of the internal collection.
Use the Builder pattern. The following example is too trivial to do the pattern justice, because it's usually recommended in cases where non-trivial object graphs need to be created; nevertheless, the basic idea is something like this:
class FooBuilder // mutable version used to prepare immutable objects
{
public int X { get; set; }
public List<string> Ys { get; set; }
public Foo Build()
{
return new Foo(x, ys);
}
}
class Foo // immutable version
{
public Foo(int x, List<string> ys)
{
this.x = x;
this.ys = new List<string>(ys); // create a copy, don't use the original
} // since that is beyond our control
private readonly int x;
private readonly List<string> ys;
…
}
Hmm I will enumerate my first thought on this...
1. Use internal setters if your only worry is manipulation outside of your assembly. internal will make your properties available to classes in the same assembly only. For example:
public class X
{
// ...
public int Field { get; internal set; }
// ...
}
2. I don't agree that it's necessarily a bad idea to have lots of parameters in your constructor.
3. You could generate another type at runtime that is a read-only version of your type. I can elaborate on this, but personally I think this is overkill.
Best, Iulian
As another solution you can use Dynamic Proxy. Alike approach was used for Entity Framework http://blogs.msdn.com/b/adonet/archive/2009/12/22/poco-proxies-part-1.aspx. Here is example how you can do it using Castle.DynamicProxy framework. This code is based on original example from Castle Dynamic proxy (http://kozmic.net/2008/12/16/castle-dynamicproxy-tutorial-part-i-introduction/)
namespace ConsoleApplication8
{
using System;
using Castle.DynamicProxy;
internal interface IFreezable
{
bool IsFrozen { get; }
void Freeze();
}
public class Pet : IFreezable
{
public virtual string Name { get; set; }
public virtual int Age { get; set; }
public virtual bool Deceased { get; set; }
bool _isForzen;
public bool IsFrozen => this._isForzen;
public void Freeze()
{
this._isForzen = true;
}
public override string ToString()
{
return string.Format("Name: {0}, Age: {1}, Deceased: {2}", Name, Age, Deceased);
}
}
[Serializable]
public class FreezableObjectInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
IFreezable obj = (IFreezable)invocation.InvocationTarget;
if (obj.IsFrozen && invocation.Method.Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase))
{
throw new NotSupportedException("Target is frozen");
}
invocation.Proceed();
}
}
public static class FreezableObjectFactory
{
private static readonly ProxyGenerator _generator = new ProxyGenerator(new PersistentProxyBuilder());
public static TFreezable CreateInstance<TFreezable>() where TFreezable : class, new()
{
var freezableInterceptor = new FreezableObjectInterceptor();
var proxy = _generator.CreateClassProxy<TFreezable>(freezableInterceptor);
return proxy;
}
}
class Program
{
static void Main(string[] args)
{
var rex = FreezableObjectFactory.CreateInstance<Pet>();
rex.Name = "Rex";
Console.WriteLine(rex.ToString());
Console.WriteLine("Add 50 years");
rex.Age += 50;
Console.WriteLine("Age: {0}", rex.Age);
rex.Deceased = true;
Console.WriteLine("Deceased: {0}", rex.Deceased);
rex.Freeze();
try
{
rex.Age++;
}
catch (Exception ex)
{
Console.WriteLine("Oups. Can't change that anymore");
}
Console.WriteLine("--- press enter to close");
Console.ReadLine();
}
}
}
I would suggest having an abstract base type ReadableMyObject along with derived types MutableMyObject and ImmutableMyObject. Have constructors for all the types accept a ReadableMyObject, and have all the property setters for ReadableMyObject call an abstract ThrowIfNotMutable method before updating their backing field. Additionally, have ReadableMyObject support a public abstract AsImmutable() method.
Although this approach will require writing some boilerplate for each property of your object, that will be the extent of the required code duplication. The constructors for MutableMyObject and ImmutableMyObject will simply pass the received object to the base-class constructor. Class MutableMyObject should implement ThrowIfNotMutable to do nothing, and AsImmutable() to return new ImmutableMyObject(this);. Class ImmutableByObject should implement ThrowIfNotMutable to throw an exception, and AsImmutable() to return this;.
Code which receives a ReadableMyObject and wants to persist its contents should call its AsImmutable() method and store the resulting ImmutableMyObject. Code which receives a ReadableMyObject and wants a slightly-modified version should call new MutableMyObject(theObject) and then modify that as required.
You kind of hinted at a way in your question, but I'm not sure if this is not an option for you:
class MyObject
{
// lots of fields painful to initialize all at once
// so we make fields mutable :
public String Title { get; protected set; }
public String Author { get; protected set; }
// ...
public MyObject(string title, string author)
{
this.Title = title;
this.Author = author;
}
}
Due to the constructor being the only way of manipulating your Author and Title, the class is in effect immutable after construction.
EDIT:
as stakx mentioned, I too am a big fan of using builders - especially because it makes unit testing easier. For the above class you could have a builder such as:
public class MyObjectBuilder
{
private string _author = "Default Author";
private string _title = "Default title";
public MyObjectBuilder WithAuthor(string author)
{
this._author = author;
return this;
}
public MyObjectBuilder WithTitle(string title)
{
this._title = title;
return this;
}
public MyObject Build()
{
return new MyObject(_title, _author);
}
}
This way you can construct your objects with default values, or override them as you please, but MyObject's properties can't be changed after construction.
// Returns a MyObject with "Default Author", "Default Title"
MyObject obj1 = new MyObjectBuilder.Build();
// Returns a MyObject with "George R. R. Martin", "Default Title"
MyObject obj2 = new MyObjectBuilder
.WithAuthor("George R. R. Martin")
.Build();
If you ever need to add new properties to your class, it's much easier to go back to your unit tests that consume from a builder rather than from a hardcoded object instantiation (i don't know what to call it, so pardon my terms).
Well, if you have too many parameters and you dont want to do constructors with parameters....here is an option
class MyObject
{
private string _title;
private string _author;
public MyObject()
{
}
public String Title
{
get
{
return _title;
}
set
{
if (String.IsNullOrWhiteSpace(_title))
{
_title = value;
}
}
}
public String Author
{
get
{
return _author;
}
set
{
if (String.IsNullOrWhiteSpace(_author))
{
_author = value;
}
}
}
// ...
}
Here's another option. Declare a base class with protected members and a derived class that redefines the members such that they are public.
public abstract class MyClass
{
public string Title { get; protected set; }
public string Author { get; protected set; }
public class Mutable : MyClass
{
public new string Title { get { return base.Title; } set { base.Title = value; } }
public new string Author { get { return base.Author; } set { base.Author = value; } }
}
}
Creating code will use the derived class.
MyClass immutableInstance = new MyClass.Mutable { Title = "Foo", "Author" = "Your Mom" };
But for all cases where immutability is expected, use the base class:
void DoSomething(MyClass immutableInstance) { ... }

c# correct way to access private constant on other class

If I have a class
public class Person
{
private const string MyConst = "SomeValue";
[MyAttribute(MyConst)]
public string Name {get;set;}
}
and inside other class I would like to access MyConst what would be the best way to do so, keeping all encapsulated? Is it correct Person class?
If you wish to access MyConst from another class then you are no longer encapsulating it. Adding properties or method calls around this will not mean it is encapsulated. It's a constant. It cannot change. So either its publicly accessible or it's not. If another class needs access, make it internal or public.
Anything else is somewhere between denial and a code smell.
It all depends on the protection you need on MyConst. If no body should be able to read or write this property other than Person then you shouldn't expose it through either Get or Set methods. If everybody can read but cant write this, then you can expose it through a read only property. If only one class (e.g. ClassB) can read it then you can provide a function in Person that takes a ClassB object and passes the private Const to it:
public class ClassB
{
private string ConstValue {get; set;}
public void SetConstValue(string constValue)
{
ConstValue = constValue;
}
public void GetConstFromPerson(Person p)
{
p.GetConstValue(this);
}
}
public class Person
{
private const string MyConst = "A";
public void GetConstValue(ClassB obj)
{
//todo: contract validations
obj.SetConstValue(MyConst);
}
}
[Edit]
Another solution is to define the constant as Internal and only have Person and CLassB in the assembly
make a public property that returns MyConst?
public string MyPublicConst {get{ return MyConst;} private set; } - but why do you want to do this?
You can have it public (Duh!), you can use a property to encapsulate it if you are planning on changing it from a constant to something else, or you could have a method that return it to you.
class Encapsulation{
private string a;
public string AccessValue(){
return a;
}
}
you can do that to any variable I think, for sure the simple ones.
This is a public method from the same class that returns the same value of the private string.
In that way you can get the value from outside the class without declare it as public.
To reach it from another class you can just write:
class Player{ string b = Encapsulaion.AccessValue()}

Caching Intensive Calculation in Property Getter

In the following code:
public class SomeClass
{
// ... constructor and other stuff
public in SomeProperty
{
get
{
return SomeHeavyCalculation();
}
}
}
I consider the class to be immutable, so every time SomeProperty is accessed, same value should be returned. My question is whether it is possible to avoid calculating the value each time. Is there some built in mechanism for caching such stuff?
Yup - Lazy<T>, assuming you're using .NET 4:
public class SomeClass
{
private readonly Lazy<Foo> foo = new Lazy<Foo>(SomeHeayCalculation);
// ... constructor and other stuff
public Foo SomeProperty
{
get
{
return foo.Value;
}
}
}
I assume you're trying to avoid performing the calculation if the property is never accessed. Otherwise, just perform it upfront on construction.
Note that properties are often understood to be "cheap" to evaluate - and while you're making this lazy so that later accesses are cheap, this is still potentially going to be "heavy" enough on the first access to make a property inappropriate. Consider a ComputeXyz method instead.
Just cache the calculation in a private variable like so:
public class SomeClass
{
// ... constructor and other stuff
private int? calculation = null;
public int SomeProperty
{
get
{
if (!calculation.HasValue)
calculation = SomeHeayCalculation();
return calculation.Value;
}
}
}
Other than what Jon suggested, you could use this pattern:
public class SomeClass
{
// ... constructor and other stuff
private Foo _foo;
public Foo SomeProperty
{
get
{
return _foo ?? (_foo = SomeHeayCalculation());
}
}
}
It's worth noting that this really breaks down (read: becomes less readable) for value types, unless you want to wrap them in Nullable<T>. In that's your case, you may want to stick with Lazy<T> if available.
Just keep a flag to remember if the calculation have been done.
public class SomeClass
{
// ... constructor and other stuff
private bool _propertyCalculated;
private int _someProperty;
public int SomeProperty
{
get
{
if (!_propertyCaculated)
{
_someProperty = SomeHeayCalculation();
_propertyCaculated = true;
}
return _someProperty;
}
}
}

C# splitting property get and set between classes. Why doesn't it work?

I'm trying to provide two classes to my users - one that is read-only and one that is writable. The r/o will only have getters, while the writable will inherit from it and add the setters.
I was under the impression that C# should be able to handle it, but the compiler disagreed.
Why doesn't this work? Any workarounds?
class A
{
protected int m_val;
public int Val
{
get { return m_val; }
}
}
class B : A
{
public int Val
{
set { m_val = value; }
}
}
class Test
{
static void Main(string[] args)
{
B b = new B();
b.Val++; // <-- WHY DOESN'T THIS WORK?!
}
}
P.S. the protected variable in the example above is artificial. My class actually wraps some native resources and the getting/setting happens on either const or mutable native pointer.
partial applies to a single type - not 2 types (A and B). You would need something more like below, ideally keeping the field private:
class A
{
private int m_val;
public int Val
{
get { return m_val; }
protected set { m_val = value; }
}
}
class B : A
{
public new int Val
{
get { return base.Val;}
set { base.Val = value; }
}
}
I'm not sure about why you need this, but a possibly better design would be to have two interfaces rather than two classes, and a single class that implements both. Then you could hand your client code whichever interface you'd like them to use, with the added bonus of being able to use the values set on a writable interface and hand it over to someone else as a read-only interface.
Mark the setters as protected in the parent, and expose public setters in the child.

recreate instance in base class

I was wondering if it is possible to change the type of an instance of a derived class in it's base class to another derived class from the same base . following I will try to explain it in a code .
public class ValueTypeClass
{
private string _Note;
private String _Name;
private nodeClass refrenceNode ;
//...
}
public class refrenceDBClass : valuetypeclass
{
//...
}
public class refrenceFileClass : valuetypeclass
{
//...
}
now each time the refrenceNode is changed I want to change the type of the instance based on the refrenceNode properties
Edit 1 :
Now I'm doing this by having another class which keeps the detail of refrencedbclass and refrencefileclass and everytime the refrencenode is changed I'm creating a new instance .
public class ValueTypeClass
{
private string _Note;
private String _Name;
private nodeClass refrenceNode ;
private detailClass detailInfo ;
//...
}
public class detailClass
{
//...
}
public class refrenceDBClass : detailClass
{
//...
}
public class refrenceFileClass : detailClass
{
//...
}
In C#, an instance never changes its type.
I don't understand the problem you want to solve with this, but I assume that you should aggregate this type you want to change, and create a new instance if some value changes. Like the strategy pattern, for instance.
You can not change the type of a managed .NET object. If you were encapsulating the object (in a wrapper - for example refrenceNode) you could swap the reference, but that is about it.
In some (limited) cases, you might be able to serialize/deserialize an encapsulated instance, changing the type in the process (only works for contract-based serializers, with compatible contracts; very unlikely). You certainly can't change the type of the current instance.
Re the edit; again, you can't change the type of how you expose the details, but with some casting you could make it work; vaguely, something like:
public class ValueTypeClass
{
private string _Note;
private String _Name;
private nodeClass refrenceNode;
public nodeClass ReferenceNode {
get {return refrenceNode;}
set {
if(refrenceNode == value) return; // nop
refrenceNode = value;
BuildDetailInfo();
}
}
private detailClass detailInfo;
public detailClass DetailInfo {get {return detailInfo;}}
private void BuildDetailInfo() {
// TODO: decide on the appropriate type (based on refrenceNode)
// and recreate detailInfo
}
}
It sounds like you should also be making use of polymorphism. If you are doing data-binding there are some other things you can do (with considerable effort) to make this more friendly, but it won't affect regular code.

Categories