A very common C# pattern that breaks a very fundamental OOP principle - c#

Here is a very simple question, which I'm still very uneasy about:
Why is it widely accepted now for a class to return a reference to its private member through an accessor method? Doesn't this totally break the encapsulation principle? If this is OK, then why not just make the member public!?
public class EncapsulationViolator
{
private object abuseMe;
public object AbuseMe
{
get { return abuseMe; }
}
}
Edit The case I was considering is this
EncapsulationViolator ev = new EncapsulationViolator();
object o = ev.AbuseMe;
o.SetValue(newValue);
Now ev's state has change through transitivity because its member abuseMe's state has changed.
In the context of DDD, this is not OK if the object is an Aggregate Root. I quote
Allow external objects to hold references to the root only. Transient
references to internal members can be passed out for use within a
single operation only. Because the root controls access, it cannot be
blindsided by changes to the internals.
[Domain-Driven Design, Eric Evans]
... setters schmetters ...

You're conflating the C++ term "reference" with the fact that C# passes objects by value (of their reference).
In this case the caller of the getter AbuseMe cannot swap out the private field abuseMe. Thus, there is no violation of encapsulation.
EncapsulationViolator x = new EncapsulationViolator();
object y = x.AbuseMe;
y = 17; // I have not changed x.AbuseMe
Debug.Assert(y != x.AbuseMe); // Passes!
Furthermore, property getters and setters allow for proper encapsulation of private fields and is functionally identical to implementing these as methods (in fact they are implemented as methods by the compiler).
One case in which returning a private variable could break encapsulation is when you return a reference to an array:
class X
{
private int[] amazing = new int[10];
public int[] Amazing { get { return this.amazing; } }
}
X a = new X();
int[] x = a.Amazing;
int[] y = a.Amazing;
x[2] = 9;
Debug.Assert(x[2] != y[2]); // Fails!

It depends on what kind of object the member is. If it for example is a string, then it's immutable, so you can't change the string.
If it is a mutable object, you can change the content of the object from outside the class, but you can't replace the object itself.
If the object should not be possible to change from outside the class, the getter should return an immutable version of the object.
The pattern could break the encapsulation if you do it wrong, but done correctly the encapsulation is intact.

I don't think it breaks encapsulation. The class still decides where the return value of AbuseMe comes from. It could come from a different member, or it could be recreated or copied every time.
Point is that the class decides what it allows users to do with that member (get/set or both and their visibility), it can perform validation and prevent invalid values to be set, and the users don't need to know where that value comes from.
Also, if you want to add custom logic to the get/set methods, you can do so without breaking compatibility with other assemblies.

It's just syntactic sugar. It's not any different from Java's getXXX and setXXX methods.

The point of the getter and setter is specifically to enforce encapsulation. The whole point is that you don't give access directly to the object, but force it to be accessed by a function that you define. Getters and setters ARE encapsulation. If you decide to just return the object, well that's your business but you aren't allowing direct access without hitting the getter.
Read this:
http://en.wikipedia.org/wiki/Mutator_method

IMO - too many answers here are promoting getters/setters. Getters/setters are great for procedural code, you either do some calculation and set the result or grab the value(s) and make some decision.
A well known principle in OO programming is Tell don't ask which basically says you shouldn't ask an object of its internal state to make a decision.
That being said, I use accessors/properties myself. However, when possible, I try to avoid them.

Related

Can an immutable type change its internal state?

The question is simple. Can a type that can change its internal state without it being observable from the outside be considered immutable?
Simplified example:
public struct Matrix
{
bool determinantEvaluated;
double determinant;
public double Determinant
{
get //asume thread-safe correctness in implementation of the getter
{
if (!determinantEvaluated)
{
determinant = getDeterminant(this);
determinantEvaluated = true;
}
return determinant;
}
}
}
UPDATE: Clarified the thread-safeness issue, as it was causing distraction.
It depends.
If you are documenting for authors of client code or reasoning as an author of client code, then you are concerned with the interface of the component (that is, its externally observable state and behavior) and not with its implementation details (like the internal representation).
In this sense, a type is immutable even if it caches state, even if it initializes lazily, etc - as long as these mutations aren't observable externally. In other words, a type is immutable if it behaves as immutable when used through its public interface (or its other intended use cases, if any).
Of course, this can be tricky to get right (with mutable internal state, you may need to concern yourself with thread safety, serialization/marshaling behavior, etc). But assuming you do get it right (to the extent you need, at least) there's no reason not to consider such a type immutable.
Obviously, from the point of view of a compiler or an optimizer, such a type is typically not considered immutable (unless the compiler is sufficiently intelligent or has some "help" like hints or prior knowledge of some types) and any optimizations that were intended for immutable types may not be applicable, if this is the case.
Yes, immutable can change its state, providing that the changes are
unseen for other components of the software (usually caches). Quite
like quantum physics: an event should have an observer to be an event.
In your case a possible implementation is something like that:
public class Matrix {
...
private Lazy<Double> m_Determinant = new Lazy<Double>(() => {
return ... //TODO: Put actual implementation here
});
public Double Determinant {
get {
return m_Determinant.Value;
}
}
}
Note, that Lazy<Double> m_Determinant has a changing state
m_Determinant.IsValueCreated
which is, however, unobservable.
I'm going to quote Clojure author Rich Hickey here:
If a tree falls in the woods, does it make a sound?
If a pure function mutates some local data in order to produce an immutable return value, is that ok?
It is perfectly reasonable to mutate objects that are expose APIs which are immutable to the outside for performance reasons. The important thing about immutable object is their immutability to the outside. Everything that is encapsulated within them is fair game.
In a way in garbage collected languages like C# all objects have some state because of the GC. As a consumer that should not usually concern you.
I'll stick my neck out...
No, an immutable object cannot change its internal state in C# because observing its memory is an option and thus you can observe the uninitialised state. Proof:
public struct Matrix
{
private bool determinantEvaluated;
private double determinant;
public double Determinant
{
get
{
if (!determinantEvaluated)
{
determinant = 1.0;
determinantEvaluated = true;
}
return determinant;
}
}
}
then...
public class Example
{
public static void Main()
{
var unobserved = new Matrix();
var observed = new Matrix();
Console.WriteLine(observed.Determinant);
IntPtr unobservedPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (Matrix)));
IntPtr observedPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Matrix)));
byte[] unobservedMemory = new byte[Marshal.SizeOf(typeof (Matrix))];
byte[] observedMemory = new byte[Marshal.SizeOf(typeof (Matrix))];
Marshal.StructureToPtr(unobserved, unobservedPtr, false);
Marshal.StructureToPtr(observed, observedPtr, false);
Marshal.Copy(unobservedPtr, unobservedMemory, 0, Marshal.SizeOf(typeof (Matrix)));
Marshal.Copy(observedPtr, observedMemory, 0, Marshal.SizeOf(typeof (Matrix)));
Marshal.FreeHGlobal(unobservedPtr);
Marshal.FreeHGlobal(observedPtr);
for (int i = 0; i < unobservedMemory.Length; i++)
{
if (unobservedMemory[i] != observedMemory[i])
{
Console.WriteLine("Not the same");
return;
}
}
Console.WriteLine("The same");
}
}
The purpose of specifying a type to be immutable is to establish the following invariant:
If two instances of an immutable type are ever observed to be equal, any publicly-observable reference to one may be replaced with a reference to the other without affecting the behavior of either.
Because .NET provides the ability to compare any two references for equality, it's not possible to achieve perfect equivalence among immutable instances. Nonetheless, the above invariant is still very useful if one regards reference-equality checks as being outside the realm of things for which a class object is responsible.
Note that under this rule, a subclass may define fields beyond those included in an immutable base class, but must not expose them in such a fashion as to violate the above invariant. Further, a class may include mutable fields provided that they never change in any way that affects a class's visible state. Consider something like the hash field in Java's string class. If it's non-zero, the hashCode value of the string is equal to the value stored in the field. If it's zero, the hashCode value of the string is the result of performing certain calculations on the immutable character sequence encapsulated by the string. Storing the result of the aforementioned calculations into the hash field won't affect the hash code of the string; it will merely speed up repeated requests for the value.

Is it possible to access a reference of a struct from a List<T> to make changes?

I have a struct which I put in a List<T>, I want to edit some value in that struct at a specific position. Is this at all possible without making a copy of the struct, editing the copy, and replacing the entry in the List?
No, to be able to do it you need reference to element of inner array which is not provided by List/IList.
You can do that with unsafe code and arrays if you have to.
From J.Richter's "CLR via C#", 3rd edition:
Value types should be immutable: that is, they should not define any
members that modify any of the type’s instance fields. In fact, I
recommended that value types have their fields marked as readonly so
that the compiler will issue errors should you accidentally write a
method that attempts to modify a field.
...
Just keep in mind that value types and reference types have very
different behaviors depending on how they’re used.
Consider this code:
public interface IChangeStruct
{
int Value { get; }
void Change(int value);
}
public struct MyStruct : IChangeStruct
{
int value;
public MyStruct(int _value)
{
value = _value;
}
public int Value
{
get
{
return value;
}
}
public void Change(int value)
{
this.value = value;
}
}
and it's usage:
static void Main(string[] args)
{
MyStruct[] l = new MyStruct[]
{
new MyStruct(0)
};
Console.WriteLine(l[0].Value);
l[0].Change(10);
Console.WriteLine(l[0].Value);
Console.ReadLine();
}
The output is:
0
10
So it does what you need.
However the same won't work for List<T>. I guess by the reason, mentioned by Alexei Levenkov. So, I would strongly recommend you to change struct to class if the type in question is not immutable per instance.
Your best bet is probably to have your structures expose their fields directly, and then use code like:
var temp = myList[3];
temp.X += 4;
myList[3] = temp;
I consider the failure of .net to provide any means of updating list items in place to be a significant weakness in .net, but would still consider an exposed-field struct as being far superior to any alternative in cases where one wishes to represent a small group of orthogonal values which should not be "attached" to any other such group (such as the coordinates in a point, the origin and size of a rectangle, etc.) The notion that structs should be "immutable" has been repeated as mantra for a long time, but that doesn't mean it's good advice. Such notion stems largely from two things:
Structs which modify `this` in any members outside their constructors are quirky. Such quirks used to (and to some extent still do) apply to property setters, but not to structs which simply expose their fields directly. Because Microsoft wrapped all struct fields in properties, this meant that while mutable structures could have had sensible semantics if they'd had exposed fields, they ended up with quirky semantics; Microsoft then blamed the quirky semantics on the fact that structs were mutable, rather than on the needless wrapping of fields with properties.
Some people like to model .net has only having one kind of object, as opposed to having value types and reference types as distinct kinds of entities. The behavior of so-called "immutable" value types is close enough to that of reference types that they can pretend they're the same thing, whereas the behavior of easily-mutable value types is vastly different. In reality, it's easier to understand the behavior of exposed-field value types than to understand all the corner cases where so-called "immutable" value types behave differently from reference types, and understanding the latter is impossible without understanding the former. Note that while value types may pretend to be immutable, there is in reality no such thing as an immutable value type. The only distinction is between those which can be mutated conveniently and those which can only be mutated awkwardly.
In reality, if a type is supposed to represent a small group of orthogonal values, an exposed-field struct is a perfect fit. Even if one has to use clunky code like that shown above to update a field of an item in a List<structType>, it's better than any alternative using class types or so-called "immutable" structs. Knowing that myList is a structure with an exposed field X would be enough to completely understand the code above. The only remotely decent alternative if one were using a class or "immutable" struct would be myList[3] = myList[3].WithX(myList[3].X + 4);, but that would require that the type in question to offer a WithX method (and presumably a WithWhatever() method for each field). Such methods would increase many fold the amount of code one would have to read to find out for certain what a method would actually do (one might expect that WithX would return a new instance which was identical to the old one except for the value of X, but one wouldn't know until one read all the code involved; by contrast, knowing that X is an exposed field of the structure type would be sufficient to know what the above code would do.

Writing access to private objects via public readOnly property

I am currently struggling to understand something i just saw somewhere.
Lets say I have two classes :
class MyFirstCLass{
public int membVar1;
private int membVar2;
public string membVar3;
private string membVar4;
public MyFirstClass(){
}
}
and :
class MySecondClass{
private MyFirstClass firstClassObject = new MyFirstClass();
public MyFirstClass FirstClassObject{
get{
return firstClassObject;
}
}
}
If i do something like this :
var secondClassObject = new MySecondClass(){
FirstClassObject = {membVar1 = 42, membVar3 = "foo"}
};
secondClass is an instanciation of MySecondClass, and does have one private member variable of type MyFirstClass wich has a readOnly property. However, i am able to change the state of membVar1 and membVar2. Isn't there any encapsulation problem ?
Best regards,
Al_th
The fact that the FirstClassObject property on MySecondClass has no setter does not mean that the object returned from the getter becomes immutable. Since it has public fields, these fields are mutable. Therefore it is perfectly legal to say secondClassObject.FirstClassObject.membVar1 = 42. The absence of the setter only means that you cannot replace the object reference stored in the firstClassObject field with a reference to a different object.
Please note: You are not changing the value of MySecondClass.FirstClassObject. You are simply changing the values inside that property.
Compare the following two snippets. The first is legal, the second is not as it tries to assign a new value to the FirstClassObject property:
// legal:
var secondClassObject = new MySecondClass(){
FirstClassObject = {membVar1 = 42, membVar3 = "foo"} }
// won't compile:
// Property or indexer 'FirstClassObject' cannot be assigned to -- it is read only
var secondClassObject = new MySecondClass(){
FirstClassObject = new MyFirstClass {membVar1 = 42, membVar3 = "foo"} }
Basically, your code is just a very fancy way of writing this:
var secondClassObject = new MySecondClass();
secondClassObject.FirstClassObject.membVar1 = 42;
secondClassObject.FirstClassObject.membVar3 = "foo";
And that's how I would write it. It is explicit and understandable.
Neither a storage location of type MyFirstCLass, nor the value returned by a a property of type MyFirstCLass, contains fields membVar1, membVar2, etc. The storage location or property instead contains information sufficient to either identify an instance of MyFirstCLass or indicate that it is "null". In some languages or frameworks, there exist reference types which identify an object but only allow certain operations to be performed on it, but Java and .NET both use Promiscuous Object References: if an object allows outside code that holds a reference to do something with it, any outside code that gets a reference will be able to do that.
If a class is using a mutable object to encapsulate its own state, and wishes to allow the outside world to see that state but not allow the outside world to tamper with it, it must not return the object directly to the outside code but instead give the outside code something else. Possibilities include:
Expose all the aspects of state encompassed by the object individually (e.g. have a membVar1 property which returns the value of the encapsulated object's membVar1). This can avoid confusion, but provides a caller with no way to handle the properties as a group.
Return a new instance of a read-only wrapper which holds a reference to the private object, and has members that forward read requests (but not write requests) to those members. The returned object will serve as a read-only "view", but outside code will have no nice way to identify whether two such objects are views of the same underlying object.
Have a field of a read-only-wrapper type which is initialized in the constructor, and have a property return that. If each object will only have one read-only wrapper associated with it, two wrapper references will view the same wrapped object only if they identify the same wrapper.
Create an immutable copy of the underlying data, perhaps by creating a new mutable copy and returning a new read-only wrapper to it. This will give the caller a "snapshot" of the data, rather than a live "view".
Create a new mutable copy of the underlying data, and return that. This has the disadvantage that a caller who tries to change the underlying data by changing the copy will be allowed to change the copy without any warnings, but the operation won't work. All of the arguments for why mutable structs are "evil" apply doubly here: code which receives an exposed-field structure should expect that changes to the received structure won't affect the source from which it came, but code which receives a mutable class object has no way of knowing that. Properties should not behave this way; such behavior is generally only appropriate for methods which make clear their intention (e.g. FirstClassObjectAsNewMyFirstClass();
Require that the caller pass in a mutable object of a type that can accept the underlying data, and copy the data into that. This gives the caller the data in a mutable form (which in some cases may be easier to work with) but at the same time avoids any confusion about who "owns" the object. As an added bonus, if the caller will be making many queries, the caller may reuse the same mutable object for all of them, thus avoiding unnecessary object allocations.
Encapsulate the data within a structure, and have a property return the structure. Some people may balk at such usage, but it's a useful convention in cases where a caller may want to piecewise-modify the data. This approach only really works if the data in question is limited to a fixed set of discrete values (such as the coordinates and dimensions of a rectangle), but has the advantage that if the caller understands what a .NET structure is (as all .NET programmers should) the semantics are inherently obvious.
Of these choices, only the last two make clear via the type system what semantics the caller should expect. Accepting a mutable object from the caller offers clear semantics, but makes usage awkward. Returning an exposed-field structure offers clear semantics but only if the data consists of a fixed set of discrete values. Returning a mutable copy of the data is sometimes useful, but is only appropriate if the method name makes clear what it is doing. The other choices generally leave ambiguous the question of whether the data represents a snapshot or a live "view".

Why does Microsoft advise against readonly fields with mutable values?

In the Design Guidelines for Developing Class Libraries, Microsoft say:
Do not assign instances of mutable types to read-only fields.
The objects created using a mutable type can be modified after they are created. For example, arrays and most collections are mutable types while Int32, Uri, and String are immutable types. For fields that hold a mutable reference type, the read-only modifier prevents the field value from being overwritten but does not protect the mutable type from modification.
This simply restates the behaviour of readonly without explaining why it's bad to use readonly. The implication appears to be that many people do not understand what "readonly" does and will wrongly expect readonly fields to be deeply immutable. In effect it advises using "readonly" as code documentation indicating deep immutability - despite the fact that the compiler has no way to enforce this - and disallows its use for its normal function: to ensure that the value of the field doesn't change after the object has been constructed.
I feel uneasy with this recommendation to use "readonly" to indicate something other than its normal meaning understood by the compiler. I feel that it encourages people to misunderstand the meaning of "readonly", and furthermore to expect it to mean something that the author of the code might not intend. I feel that it precludes using it in places it could be useful - e.g. to show that some relationship between two mutable objects remains unchanged for the lifetime of one of those objects. The notion of assuming that readers do not understand the meaning of "readonly" also appears to be in contradiction to other advice from Microsoft, such as FxCop's "Do not initialize unnecessarily" rule, which assumes readers of your code to be experts in the language and should know that (for example) bool fields are automatically initialised to false, and stops you from providing the redundancy that shows "yes, this has been consciously set to false; I didn't just forget to initialize it".
So, first and foremost, why do Microsoft advise against use of readonly for references to mutable types? I'd also be interested to know:
Do you follow this Design Guideline in all your code?
What do you expect when you see "readonly" in a piece of code you didn't write?
It seems natural that if a field is readonly, you would expect to not be able to change the value or anything having to do with it. If I knew that Bar was a readonly field of Foo, I could obviously not say
Foo foo = new Foo();
foo.Bar = new Baz();
But I can get away with saying
foo.Bar.Name = "Blah";
If the object backing Bar is, in fact, mutable. Microsoft is simply recommending against that subtle, counterintuitive behavior by suggesting that readonly fields be backed by immutable objects.
I agree with you completely, and I do sometimes use readonly in my code for mutable reference types.
As an example: I might have some private or protected member -- say, a List<T> -- which I use within a class's methods in all its mutable glory (calling Add, Remove, etc.). I may simply want to put a safeguard in place to ensure that, no matter what, I am always dealing with the same object. This protects both me and other developers from doing something stupid: namely, assigning the member to a new object.
To me, this is often a preferable alternative to using a property with a private set method. Why? Because readonly means the value cannot be changed after instantiation, even by the base class.
In other words, if I had this:
protected List<T> InternalList { get; private set; }
Then I could still set InternalList = new List<T>(); at any arbitrary point in code in my base class. (This would require a very foolish error on my part, yes; but it would still be possible.)
On the other hand, this:
protected readonly List<T> _internalList;
Makes it unmistakably clear that _internalList can only ever refer to one particular object (the one to which _internalList is set in the constructor).
So I am on your side. The idea that one should refrain from using readonly on a mutable reference type is frustrating to me personally, as it basically presupposes a misunderstanding of the readonly keyword.
DO NOT assign instances of mutable types to readonly fields.
I had a quick look in the Framework Design Guidelines book (pages 161-162), and it basically states what you've already noticed yourself. There's an additional comment by Joe Duffy that explains the guideline's raison-d'être:
What this guideline is trying to protect you from is believing you've exposed a deeply immutable object graph when in fact it is shallow, and then writing code that assumes the whole graph is immutable. — Joe Duffy
I personally think that the keyword readonly was named badly. The fact that it only specifies the const-ness of the reference, and not of the const-ness of the referenced object, easily creates misleading situations.
I think it would have been preferable if readonly made referenced objects immutable, too, and not just the reference, because that is what the keyword implies.
To remedy this unfortunate situation, the guideline was made up. While I think that its advice is sound from the human point of view (it's not always obvious which types are mutable and which aren't without looking up their definition, and the word suggests deep immutability), I sometimes wish that, when it comes to declaring const-ness, C# would offer a freedom similar to that offered by C++, where you can define const either on the pointer, or on the pointed-to-object, or on both or nothing.
The syntax you are looking for is supported by the C++/CLI language:
const Example^ const obj;
The first const makes the referenced object immutable, the 2nd makes the reference immutable. The latter is equivalent to the readonly keyword in C#. Attempts to evade it produce a compile error:
Test^ t = gcnew Test();
t->obj = gcnew Example(); // Error C3892
t->obj->field = 42; // Error C3892
Example^ another = t->obj; // Error C2440
another->field = 42;
It is however smoke and mirrors. The immutability is verified by the compiler, not by the CLR. Another managed language could modify both. Which is the root of the problem, the CLR just doesn't have support for it.
Microsoft has a few such peculiar advices. The other one that immediately springs to mind is not to nest generic types in public members, like List<List<int>>. I try to avoid these constructs where easily possible, but ignore the newbie-friendly advice when I feel the use is justified.
As for readonly fields - I try to avoid public fields as such, instead going for properties. I think there was a piece of advice about that too, but more importantly there are cases now and then when a field doesn't work while a property does (mostly it has to do with databinding and/or visual designers). By making all public fields properties I avoid any potential problems.
In the end they are just guidelines. I know for a fact that the people at Microsoft often don't follow all of the guidelines.
This is legal in C# (simple Console App)
readonly static object[] x = new object[2] { true, false };
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
x[0] = false;
x[1] = true;
Console.WriteLine("{0} {1}", x[0], x[1]); //prints "false true"
Console.ReadLine();
}
that would work. but that wouldn't make sense. bear in mind the variable x is readonly, and has not changed (i.e. the ref of x has not changed indeed). but that's not what we meant when we said "readonly x", is it? so don't use readonly fields with mutable values. It's confusing and counter-intuitive.

Why can '=' not be overloaded in C#?

I was wondering, why can't I overload '=' in C#? Can I get a better explanation?
Memory managed languages usually work with references rather than objects. When you define a class and its members you are defining the object behavior, but when you create a variable you are working with references to those objects.
Now, the operator = is applied to references, not objects. When you assign a reference to another you are actually making the receiving reference point to the same object that the other reference is.
Type var1 = new Type();
Type var2 = new Type();
var2 = var1;
In the code above, two objects are created on the heap, one referred by var1 and the other by var2. Now the last statement makes the var2 reference point to the same object that var1 is referring. After that line, the garbage collector can free the second object and there is only one object in memory. In the whole process, no operation is applied to the objects themselves.
Going back to why = cannot be overloaded, the system implementation is the only sensible thing you can do with references. You can overload operations that are applied to the objects, but not to references.
If you overloaded '=' you would never be able to change an object reference after it's been created.
... think about it - any call to theObjectWithOverloadedOperator=something inside the overloaded operator would result in another call to the overloaded operator... so what would the overloaded operator really be doing ? Maybe setting some other properties - or setting the value to a new object (immutability) ?
Generally not what '=' implies..
You can, however, override the implicit & explicit cast operators:
http://www.blackwasp.co.uk/CSharpConversionOverload.aspx
Because it doesn't really make sense to do so.
In C# = assigns an object reference to a variable. So it operates on variables and object references, not objects themselves. There is no point in overloading it depending on object type.
In C++ defining operator= makes sense for classes whose instances can be created e.g. on stack because the objects themselves are stored in variables, not references to them. So it makes sense to define how to perform such assignment. But even in C++, if you have set of polymorphic classes which are typically used via pointers or references, you usually explicitly forbid copying them like this by declaring operator= and copy constructor as private (or inheriting from boost::noncopyable), because of exactly the same reasons as why you don't redefine = in C#. Simply, if you have reference or pointer of class A, you don't really know whether it points to an instance of class A or class B which is a subclass of A. So do you really know how to perform = in this situation?
Actually, overloading operator = would make sense if you could define classes with value semantics and allocate objects of these classes in the stack. But, in C#, you can't.
One possible explanation is that you can't do proper reference updates if you overload assignment operator. It would literally screw up semantics because when people would be expecting references to update, your = operator may as well be doing something else entirely. Not very programmer friendly.
You can use implicit and explicit to/from conversion operators to mitigate some of the seeming shortcomings of not able to overload assignment.
I don't think there's any really particular single reason to point to. Generally, I think the idea goes like this:
If your object is a big, complicated object, doing something that isn't assignment with the = operator is probably misleading.
If your object is a small object, you may as well make it immutable and return new copies when performing operations on it, so that the assignment operator works the way you expect out of the box (as System.String does.)
You can overload assignment in C#. Just not on an entire object, only on members of it. You declare a property with a setter:
class Complex
{
public double Real
{
get { ... }
set { /* do something with value */ }
}
// more members
}
Now when you assign to Real, your own code runs.
The reason assignment to an object is not replaceable is because it is already defined by the language to mean something vitally important.
It's allowed in C++ and if not careful , it can result in a lot of confusion and bug hunting.
This article explains this in great detail.
http://www.relisoft.com/book/lang/project/14value.html
Because shooting oneself in the foot is frowned upon.
On a more serious note one can only hope you meant comparison rather than assignment. The framework makes elaborate provision for interfering with equality/equivalence evaluation, look for "compar" in help or online with msdn.
Being able to define special semantics for assignment operations would be useful, but only if such semantics could be applied to all situations where one storage location of a given type was copied to another. Although standard C++ implements such assignment rules, it has the luxury of requiring that all types be defined at compile time. Things get much more complicated when Reflection and and generics are added to the list.
Presently, the rules in .net specify that a storage location may be set to the default value for its type--regardless of what that type is--by zeroing out all the bytes. They further specify that any storage location can be copied to another of the same type by copying all the bytes. These rules apply to all types, including generics. Given two variables of type KeyValuePair<t1,t2>, the system can copy one to another without having to know anything but the size and alignment requirements of that type. If it were possible for t1, t2, or the type of any field within either of those types, to implement a copy constructor, code which copied one struct instance to another would have to be much more complicated.
That's not to say that such an ability offer some significant benefits--it's possible that, were a new framework being designed, the benefits of custom value assignment operators and default constructors would exceed the costs. The costs of implementation, however, would be substantial in a new framework, and likely insurmountable for an existing one.
This code is working for me:
public class Class1
{
...
public static implicit operator Class1(Class2 value)
{
Class1 result = new Class1();
result.property = value.prop;
return result;
}
}
Type of Overriding Assignment
There are two type to Override Assignment:
When you feel that user may miss something, and you want force user to use 'casting'
like float to integer, when you loss the floating value
int a = (int)5.4f;
When you want user to do that without even notice that s/he changing the object type
float f = 5;
How to Override Assignment
For 1, use of explicit keyword:
public static explicit override ToType(FromType from){
ToType to = new ToType();
to.FillFrom(from);
return to;
}
For 2, use of implicit keyword:
public static implicit override ToType(FromType from){
ToType to = new ToType();
to.FillFrom(from);
return to;
}
Update:
Note: that this implementation can take place in either the FromType or ToType class, depending on your need, there's no restriction, one of your class can hold all the conversions, and the other implements no code for this.

Categories

Resources