I created a struct, that has another struct as a property. I want to be able to do something like this:
MyColor.RGBColor.R = 255;
MyColor and RGBColor being the structs I created. This doesn't work, I set a whole new value to RGBColor, but that's not straightforward and there has to be an easier way. Currently, I have to do this:
MyColor.RGBColor = new RGBColor(255, MyColor.RGColor.G ...)
I'm pretty sure if I stopped encapsualting the private properties in public properties, and just make them public in the first place, I won't have this problem... but I always read that this is a bad thing to do, so how can I go about this? Thanks
EDIT:
This is how I implement the properties currently:
private rgbcolor _RGBColor;
public rgbcolor RGBColor {
get {
return _RGBColor;
}
set {
_RGBColor = value;
}
}
This is expected behavior. By accessing the property RGBColor, you invoke its getter method, which returns the struct's instance by value. Even though you would then assign (which, in fact, even doesn't compile) a value into R, the struct itself is not stored back into the RGBColor property — even if it had a setter. This is just how value types behave.
If you can, just avoid using structs. In the world of classes with automatic references and properties with getter/setter methods they tend to be very counter-intuitive. Trying to represent small classes (in terms of data size) as structs is premature optimization.
Note: What you call a “private property” is not a property. It's a member field.
You should look at conventions for class names vs. variable names. You seem to have it somewhat backwards in your implementation.
Here's what I think you're trying to do:
private rgbcolor _RGBColor = new rgbcolor();
public rgbcolor RGBColor {
get {
return _RGBColor;
}
}
Once that's in place, you should be able to do something like (assuming there's a property R on rgbcolor)
MyColor.RGBColor.R = 255;
This will work because the instance for MyColor.RGBColor will exist when the RGBColor property is accessed.
When you use value types (structs) you should keep in mind that passing them in methods as parameters or returning from methods (also in some other cases) always cause making a copy of that object. Properties are just the methods after compilation. So your code in fact equal:
var copy = MyColor.RGBColor; // you get a copy now
copy.R = 255; // and now you change a copy, not the original object's value
C# compiller understand that this is an error and don't compile your desired variant. Because of this it's strongly recomended to create imutable structs. In your case it's better to use classes.
Related
I frequently find myself wanting to do something along these lines:
Form form = new Form();
form.ClientSize.Width = 500;
Of course the compiler will now complain that this code is not valid, since ClientSize is a property, and not a variable.
We can fix this by setting the ClientSize in its entirety:
form.ClientSize = new Size(500, ClientSize.Height);
Or, in general:
Size s = form.ClientSize;
s.Width = 500;
form.ClientSize = s; //only necessary if s is a value-type. (Right?)
But this is all looks unnecessary and obfuscated. Why can't the compiler do this for me? And of course, I'm asking about the general case, possibly involving even deeper levels of properties, not just the mundane example above
Basically, I'm asking why there is no syntactic sugar to translate the line form.ClientSize.Width = 500 into the above code. Is this simply a feature which hasn't yet been implemented, is it to avoid stacking of side effects from different getters and setters, to prevent confusion when one of the setters isn't defined, or is there a completely different reason why something like this doesn't exist?
Why can't the compiler do this for me?
It can. In fact, if you were programming in VB it would do exactly that. The C# compiler doesn't do this because it generally takes the philosophy of doing what you tell it to do; it is not a language that tries to guess at what you want to do and do that instead. If you tell it to do something silly, it'll just let you do something silly. Now this particular case is such a common source of bugs, and given these exact semantics is virtually certain to be a bug, so it does result in an error, because it's nice like that.
C# programmers learn to rely on the C# compiler never deciding to do something that you never told it to do, which can be a cause of confusion and problems when the compiler guess wrong about what you wanted to do.
I believe that you have a fundamental misunderstanding of .NET here. You can set properties of properties all day for class types because you're modifying the data of a reference without changing the reference. Take this code for example which compiles and runs fine:
class Program
{
public class Complex1
{
public Complex2 Complex2Property { get; set; }
}
public class Complex2
{
public int IntProperty { get; set; }
}
static void Main( string[] args )
{
// You must create instances of all properties to avoid a NullReferenceException
// prior to accessing said properties
var complex1 = new Complex1();
complex1.Complex2Property = new Complex2();
// Set property of property
complex1.Complex2Property.IntProperty = 7;
}
}
I assume your object is a struct or value type. The reason you can't do this for structs is that a struct is a value type - it gets copied around by value, not reference. So if I changed the above example to make Complex2 a struct, I could not do this line:
complex1.Complex2Property.IntProperty = 7;
Because the property is syntactic sugar for a get method which would return the struct by value which means a copy of the struct, not the same struct that the property holds. This means my change to that copy would not affect the original property's struct at all, accomplishing nothing except modifying a copy of my data that isn't the data in my property.
As for why the compiler doesn't do this for you? it definitely could, but it won't because you'd never want to actually do this. There's no value in modifying a copy of an object that you don't actually reassign to your property. This situation is a common error for developers who don't understand value vs reference types entirely (myself included!) and so the compiler chooses to warn you of your mistake.
For the compiler to allow myForm.ClientSize.Width = 500;, one of two things would be necessary: either the compiler would have to assume that the intended behavior is equivalent to:
var temp = myForm.ClientSize;
temp.Width = 500;
myForm.ClientSize = temp;
or else myForm would have to associate the name ClientSize with a method whose signature was:
void actupon_ClientSize<TParam>(ref Rectangle it, ref TParam param);
in which case the compiler could generate code similar to
myForm.actupon_ClientSize<int>((ref Rectangle r, ref int dummy)=>r.Width = 500, ref someDummyIntvar);
where someDummyIntVar would be an arbitrary value of type int [the second ref parameter would make it possible to pass parameters to the lambda without generating a closure]. If the Framework described a standard way for objects to properties to be exposed like that, it would make many types of programming safer and more convenient. Unfortunately, no such feature exists nor do I expect any future version of .NET to include it.
With regard to the first transformation, there are many cases where it would yield the desired effect, but also many where it would be unsafe. IMHO, there is no good reason why .NET shouldn't specify attributes which would indicate when various transformations are and are not safe, but they need for them has existed since Day One, and since the programmers responsible for .NET have consistently decided that they'd rather declare mutable structures to be "evil" than do anything that would make them be not evil, I doubt that will ever change either.
I am new to C#. i was going through a tutorial. and it shows how to create accesor-mutator to a variable as shown below;
public String var1 {
get {return "";}
set {someVar = value;}
}
1.) Can't i create getters and setter like created in java
public getVar() {return "";}
public setVar(String x){var=x;}
2.) What is value used in C# ?
You can, but that's much more annoying to use, and ignores C# coding guidelines.
value is the implicit parameter to the setter. It contains the value that the caller is setting the property to. (the right side of the Property = something call)
See the documentation.
Sure you can. Properties in C# are designed to be syntactic sugar for just that. Under the hood a property is little more than a get/set method. It's just easier to create the two methods, it keeps the two methods in one place in the source code, it has simpler syntax for the caller, and properties that do nothing but just get/set a value are easier still to generate.
It's a keyword. It is the value that is being passed into the method. If someone enters obj.var1 = "abc"; then value will be a reference to "abc".
Sure, you can do it like Java. But why? Property syntax allows a much better experience from the caller's point of view.
value is a pseudo-variable that you can use to set your internal variable with, etc. It's equivalent to x in your Java-like example.
yes you can create getter setters as in java
example
int marks;
public void setMarks(int marks)
{
this.marks=marks;
}
public int getMarks()
{
return marks;
}
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.
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.
Value types behavior shows that whatever value we are holding cannot be changed through some other variable .
But I still have a confusion in my mind about what i mentioned in the title of this post . Can anyone clarify?
Value types can be either mutable or (modulo some weird edge cases) immutable, depending on how you write them.
Mutable:
public struct MutableValueType
{
public int MyInt { get; set; }
}
Immutable:
public struct ImmutableValueType
{
private readonly int myInt;
public ImmutableValueType(int i) { this.myInt = i; }
public int MyInt { get { return this.myInt; } }
}
The built-in value types (int, double and the like) are immutable, but you can very easily create your own mutable structs.
One piece of advice: don't. Mutable value types are a bad idea, and should be avoided. For example, what does this code do:
SomeType t = new SomeType();
t.X = 5;
SomeType u = t;
t.X = 10;
Console.WriteLine(u.X);
It depends. If SomeType is a value type, it prints 5, which is a pretty confusing result.
See this question for more info on why you should avoid mutable value types.
all primitive value types like int, double,float are immutable.But structs by itself are mutable.so you have to take measures to make them as immutable as it can create lot of confusions.
Any value-type instance which holds any information can be mutated by code which can write the storage location wherein it are contained, and no value type-instance can be mutated by code which cannot write the storage location wherein it is contained. These characteristics make privately-held storage locations of mutable value types ideal data containers in many scenarios, since they combine the updating convenience that stems from mutability, with the control that would come from immutability. Note that it is possible to write the code for a value type in such a way that it's impossible to mutate an existing instance without first having an instance (perhaps a newly created temporary instance) which contains the desired data, and overwriting the contents of the former instance with the contents of the latter, but that won't make the value type any more or less mutable than it would have been absent such ability. In many cases, it merely serves to make mutation awkward and to make it look as though a statement like:
MyKeyValuePair =
new KeyValuePair<long,long>(MyKeyValuePair.Key+1, MyKeyValuePair.Value+1>;
will create a new instance but leave the existing instance unaffected. If KeyValuePair were an immutable class, and one thread was performing a MyKeyValuePair.ToString() while another thread was executing the above code, the ToString call would act upon either the old or new instance, and would thus yield either both old values or both new values. Because KeyValuePair is a struct, however, the above statement will create a new instance, but it won't make MyKeyValuePair refer to the new instance--it will merely use the new instance as a template whose fields will be copied to MyKeyValuePair. If KeyValuePair were a mutable struct, the most natural expression of the likely-intended meaning for the above code would be more like:
MyKeyValuePair.Key += 1;
MyKeyValuePair.Value += 1;
or perhaps:
var temp = MyKeyValuePair;
MyKeyValuePair.Key = temp.Key+1;
MyKeyValuePair.Value = temp.Value+1;
and the threading implications would be much clearer.