Privately scoped variable only for use within property - c#

Is it possible to have a variable which is an instance variable within a class but can only be accessed by a specific property?
I quite often create "self-creating" properties like so ...
private IWGSLocation _location;
public IWGSLocation Location
{
get
{
_location = _location ?? new WGSLocation();
_location.Latitude = Latitude.GetValueOrDefault(0);
_location.Longitude = Longitude.GetValueOrDefault(0);
return _location;
}
}
which means that I don't go re-creating a new WGSLocation (or whatever other kind of object I need, which may be expensive to create, or may only need to be created once) every time I access the property. The downside is that my class can access the _location variable. But I don't really want it to, so if there any way of having an instance variable which can only be used within the property itself?
I'm thinking something along these lines ...
public IWGSLocation Location
{
get
{
WGSLocation _location = _location ?? new WGSLocation();
_location.Latitude = Latitude.GetValueOrDefault(0);
_location.Longitude = Longitude.GetValueOrDefault(0);
return _location;
}
}

I agree it would be a nice language feature to have persistent locals -- that is, variables whose lifetimes are based on the lifetime of the instance but whose scopes (the region of program text in which it is legal to access the variable by name) are local. It would be nice to have "static" locals as well, as some languages do.
Sadly, this is not a feature of C# and we have no plans to add it. It's nice to have, but nice to have is not good enough to justify the expense, or to postpone or cancel a "nicer to have" feature.
It's only "nice to have" because of course if you have a private field, it already is a private implementation detail of the class. If you don't want it used outside the property, then don't write code that uses it outside the property. If one of your coworkers tries to do so, put the smack down on 'em in code review.
I thought I might add: be very careful when writing property getters that mutate state. By default property getters are evaluated while looking at an object in the debugger, and it can be very confusing to be debugging something and have the debugger changing the values of fields just because you are examining an object.

The fact that the class can access it isn't necessarily a downside. It is still logically encapsulated in the same entity.
What you are after isn't possible in the way you want it to be. Member variables are visible by all areas of the class and local variables are restricted to their defined scope.
What you could instead do is have the location wrapped inside a container class. This class is your member variable. When returning the IWGSLocation you simply drill into the container class:
public class LocationContainer
{
public IWGSLocation InnerLocation { get; private set; }
public void SetLocation(WGSLocation loc)
{
InnerLocation = loc;
}
}
private readonly LocationContainer _container = new LocationContainer();
public IWGSLocation Location
{
get
{
if (_container.InnerLocation == null)
{
_container.SetLocation(...);
}
return _container.InnerLocation;
}
}
This won't stop the class from touching _container, but it will make other developers think twice before they do and they won't be able to accidentally mutate the location without explicitly calling SetLocation.
You could even then put set-once guarding in the SetLocation of the container.
Update: I'd actually use the lazy class here, something like:
private readonly Lazy<IWGSLocation> _location = new Lazy<IWGSLocation>(()
=>
{
var l = new WGSLocation();
l.Latitude = Latitude.GetValueOrDefault(0);
l.Longitude = Longitude.GetValueOrDefault(0);
return l;
});
public IWGSLocation Location
{
get { return _location.Value; }
}
Be warned, this was head-compiled! :-)

Your current implementation looks broken to me.
var x=obj.Location;
x.Latitude = 1;
Console.WriteLine(x.Latitude);//1
var y=obj.Location;
Console.WriteLine(x.Latitude);//WTF it changed
I recommend making IWGSLocation immutable, or only modifying it on creation, depending on which semantics you want.

Related

making a variable only settible through its set property

I have a boolean variable, I want every change to its value to invoke a piece of code.
my current solution is the following:
bool _manualControl;
bool manualControl {
get {
return _manualControl;
}
set {
this._manualControl = value;
GlobalEventManager.ManualControlEvent?.Invoke(value);
}
}
this solution has two problems:
the value of "_manualControl" can be changed internally without invoking my piece of code, I want to prevent that.
I would prefer to avoid using two variables to get the desired behavior.
Is there any way to achieve what I want while avoiding these two specified issues?
You can set the property to be public and have a private backing field that can only be modified from within the class, which you have control of.
Or you could use an Aspect Oriented Programming framework like PostSharp, which would allow you to use an auto property and annotate it with the behaviour you desire. This would remove the need for you to have a backing field.
To me this sounds a bit like you want to solve an architectural problem, aka code smell. Why is it that you fear your field might be set outside your setter? Is it a particularly large class that a lot of people are chaning without really knowing what it is doing?
Why even have code in the setter? Like you could just redesign your code to have a method do what your setter code does and introduce that into your code flow / process.
And have a Unit Test validate your desired behavior.
If you want to:
ensure that the setter code always executes when a new value is assigned (inside and outside of the class)
avoid having two members in the class, that represent a single value
Then this can be approached by wrapping the value within a struct like one below:
struct Intercepted<T>
{
private readonly Action<T> _onChange;
private T _value;
public Intercepted(Action<T> onChange, T initialValue = default(T))
{
_onChange = onChange;
_value = initialValue;
}
public T Value
{
get
{
return _value;
}
set
{
_value = value;
_onChange?.Invoke(value);
}
}
}
In the class, ManualControl can now be represented with a single member, of type Intercepted<bool>:
public Intercepted<bool> ManualControl { get; } = new ManualControl(
onChange: newValue => {
GlobalEventManager.ManualControlEvent?.Invoke(newValue);
}
);
The value can be accessed like this:
// from within the class
if (ManualControl.Value) { ... }
// from outside
myObj.ManualControl.Value = true;
Now there is no way to change the value without triggering the setter code, both inside and outside the class.

Eliminate Duplicate C# Property Bodies

I am building a large, complex data structure with many interconnected objects. As part of this, I have a situation where I need to create an object before I know the values for all the properties. This is so I can pass a reference to that object around inside of a larger data structure, then change it later to allow all the consumers of that object to get the "updated" values.
Tracking the consumers of each object so I can go update their references means I am A) re-implementing a reference counting garbage collector and B) would require an external consumer to modify a class. For obvious reasons, I don't want to implement a garbage collector (or something similar). and allowing external consumers to modify properties means the object is mutable. Immutability is important because I know that many objects in this data structure are going to wind up in Dictionaries after the data structure has been built, but I can safely modify properties until then. Since this is going into a library that will be provided to other users, I must block interactions that will break things like invariants for Dictionaries.
I am implementing this "deferred initialization" concept for properties like this:
class MyClass
{
private AnotherClass mReference = null;
public bool Reference
{
get
{
return this.mReference
}
internal set
{
if ( this.mReference != null )
{
throw new Exception( "This value has already been initialized!" );
}
else
{
this.mReference = value;
}
}
}
}
I am allowing anything in the internal scope to assign a non-null value to this property exactly once. Once the property has been set, there's no going back.
While C# has a keyword readonly that sort of already does this, readonly constrains the member to only be assigned to via either a static initializer or a constructor in the same class. But at the time the constructor is called, I don't know what the value for this property is!
My problem is I am now using this exact pattern across multiple classes, and I would like to avoid this code duplication.
Does anyone have any suggestions for how I can reduce the code duplication? Maybe a C# keyword like readonly, or some other language feature? Or is this just not possible? Unfortunately, it is not possible to refactor the algorithms such that I can delay instantiation of all objects until all values are known. Think of bidirectional relationships with immutable objects at each end if you need an example of this scenario.
Just encapsulate the behavior in its own type:
public sealed class OneTimeAssignable<T> where T : class
{
public T Value
{
get
{
return mValue;
}
set
{
if( mValue != null ) throw new InvalidOperationException( "Value can only be assigned once." );
mValue = value;
}
}
private T mValue;
}
Now you can use it as the backing field for your properties:
class MyClass
{
private readonly OneTimeAssignable<AnotherClass> mReference = new OneTimeAssignable<AnotherClass>();
public AnotherClass Reference
{
get
{
return this.mReference.Value;
}
internal set
{
this.mReference.Value = value;
}
}
}
Right now I have it set to only work on reference types (and assuming you don't want them to ever be set to null), but it's easy enough to modify it to accept value types as well, but requires adding a bool to track whether the property has been set.

MethodBase as Hashtable Key

I want to store some backing fields of Properties declared in derived classes in protected Hashtable contained in base class.
The usage of this mechanism in derived classes has to beas simple as possible.
So, can I use MethodBase.GetCurrentMethod() to provide information about calling property (getter - properties are read-only), so it can be recognized as the one and only property that has access to this particular backing field?
EDIT:
Basically, I want to implement pattern:
private SomeClass _someProperty = null;
private SomeClass SomeProperty
{
if (_someProperty == null)
{
_someProperty = new SomeClass();
}
return _someProperty;
}
to look something like this:
private SomeClass SomeProperty
{
return GetProperty(delegate
{
var someProperty = new SomeClass();
return someProperty;
};
}
And in base class
private System.Collections.Hashtable _propertyFields = new System.Collections.Hashtable();
protected T GetProperty<T>(ConstructorDelegate<T> constructorBody)
{
var method = new System.Diagnostics.StackFrame(1).GetMethod();
if (!_propertyFields.ContainsKey(method))
{
var propertyObject = constructorBody.Invoke();
_propertyFields.Add(method, propertyObject);
}
return (T)_propertyFields[method];
}
protected delegate T ConstructorDelegate<T>();
The reason I want to do this is to simplify the usage of properties.
I use private properties to create some objects and use them around the class. But when I store their backing fields in the same class, I have the same access to them as to the properties, so I (means user who would create some derived classes in the future) could accidently use backing field instead of the property, so I wanted to restrict access to backing field, while allow to create object and use it.
I tried to use ObsoleteAttribute on the backing fields like this:
[Obsolete("Don't use this field. Please use corresponding property instead.")]
private SomeClass __someProperty;
private SomeClass _someProperty
{
#pragma warning disable 0618 //Disable Obsolete warning for property usage.
get
{
if (__someProperty== null)
{
__someProperty = new SomeClass();
}
return __someProperty ;
}
#pragma warning restore 0618 //Restore Obsolete warning for rest of the code.
}
But, firstly, I cannot force the user to use this pattern, and secondly, it's to much code to write in derived class, which, as I metioned above, I want to be as simple as possible.
Neither MethodBase nor MemberInfo do not properly overrides Equals and GetHashCode functions, but uses default RuntimeHelpers.GetHashCode and RuntimeHelpers.Equals. So you will only be able to compare same instance, but not same content. In most cases this will be enough as runtime caches that instances to reuse them. But there is no guarantee this will work stable.
As you working with metadata, use something that will identify it uniquely. For example, MemberInfo.MetadataToken. You could write your own comparer and use it inside hashtable:
public class MethodBaseComparer : IEqualityComparer<MethodBase>
{
public bool Equals(MethodBase x, MethodBase y)
{
if (ReferenceEquals(x, y))
return true;
if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
return false;
return x.MetadataToken.Equals(y.MetadataToken) &&
x.MethodHandle.Equals(y.MethodHandle);
}
public int GetHashCode(MethodBase obj)
{
return (obj.MetadataToken.GetHashCode() * 387) ^ obj.MethodHandle.GetHashCode();
}
}
It not a good idea to restrict access via reflection to some members as other trusted code can use reflection to access other private data outflanking your checks. Consider restrict access via redesigning your classes.
Also take a look at Code Access Security.
Update according to your edit.
You told your properties are read-only. I guess, simply declaring them as readonly is not your option. Looks like you want delayed initialization for properties values. In that case you will not able to declare them as readonly. Right?
Or maybe you can?
Take a look at Lazy<T> class. It's not available in dotnet 2.0, but you can easily implement it or even take any existing implementation (just replace Func<T> with your delegate). Example usage:
public class Foo
{
private readonly Lazy<int> _bar = new Lazy<int>(() => Environment.TickCount, true);
// similar to your constructorBody - ^^^^^^^^^^^^^^^^^^^^^^^^^^^
private int Bar
{
get { return this._bar.Value; }
}
public void DoSomethingWithBar(string title)
{
Console.WriteLine("cur: {0}, foo.bar: {1} <- {2}",
Environment.TickCount,
this.Bar,
title);
}
}
Pros:
It's a lazy initialization as you wish. Let's test it:
public static void Main()
{
var foo = new Foo();
Console.WriteLine("cur: {0}", Environment.TickCount);
Thread.Sleep(300);
foo.DoSomethingWithBar("initialization");
Thread.Sleep(300);
foo.DoSomethingWithBar("later usage");
}
Output will be something like this:
cur: 433294875
cur: 433295171, foo.bar: 433295171 <- initialization
cur: 433295468, foo.bar: 433295171 <- later usage
Note, value initialized on first access and not changed later.
Properties are write-protected by a compiler - _bar field is readonly and you have no access to internal fields of Lazy<T>. So, no any accidental backing field usage. If you try you will get compilation error on type mismatch:
CS0029 Cannot implicitly convert type System.Lazy<SomeClass> to SomeClass
And even if you access it via this._bar.Value, nothing terrible would happen and you will get a correct value as if you access it via this.Bar property.
It is much more simpler, faster and easier to read and maintain.
Thread safety out of the box.
Cons: — (I didn't found)
Few cents about your hashtable-based design:
You (or someone who will maintain your code) can accidentally (or advisedly) access and/or modify either whole hashtable or it's items as it is just a usual private property.
Hashtable is a minor performance hit + getting stacktrace is a huge performance hit. However I don't know if it is critical, depends on how often you access your properties.
It would be hard to read and maintain.
Not thread safe.

More private than private? (C#)

Sometimes you have a private field that backs a property, you only ever want to set the field via the property setter so that additional processing can be done whenever the field changes. The problem is that it's still easy to accidentally bypass the property setter from within other methods of the same class and not notice that you've done so. Is there a way in C# to work around this or a general design principle to avoid it?
IMHO, it is not used, because:
The class must trust itself
If your class gets as large that one part does not know the other, it should be divided.
If the logic behind the property is slightly more complex, consider to encapsulate it in an own type.
I'd consider this a nasty hack and try to avoid it if possible, but...
You can mark the backing field as obsolete so that the compiler will generate a warning when you try to access it, and then suppress that warning for the property getter/setter.
The warning codes that you'd need to suppress are CS0612 for the plain Obsolete attribute and CS0618 if the attribute has a custom message.
[Obsolete("Please don't touch the backing field!")]
private int _backingField;
public int YourProperty
{
#pragma warning disable 612, 618
get { return _backingField; }
set { _backingField = value; }
#pragma warning restore 612, 618
}
There's no inbuilt way to do what you want to do, but by the sounds of things you need another layer of abstraction between your class and that value.
Create a separate class and put the item in there, then your outer class contains the new class, and you can only access it through its properties.
No, there isn't. I'd quite like this myself - something along the lines of:
public string Name
{
private string name; // Only accessible within the property
get { return name; /* Extra processing here */ }
set { name = value; /* Extra processing here */ }
}
I think I first suggested this about 5 years ago on the C# newsgroups... I don't expect to ever see it happen though.
There are various wrinkles to consider around serialization etc, but I still think it would be nice. I'd rather have automatically implemented readonly properties first though...
You CAN do this, by using a closure over a local in the constructor (or other initialisation function). But it requires significantly more work that the helper class approach.
class MyClass {
private Func<Foo> reallyPrivateFieldGetter;
private Action<Foo> reallyPrivateFieldSetter;
private Foo ReallyPrivateBackingFieldProperty {
get { return reallyPrivateFieldGetter(); }
set { reallyPrivateFieldSetter(value); }
}
public MyClass() {
Foo reallyPrivateField = 0;
reallyPrivateFieldGetter = () => { return reallyPrivateField; }
reallyPrivateFieldSetter = v => { reallyPrivateField = v; };
}
}
I suspect that the underlying field type Foo will need to be a reference class, so the two closures are created over the same object.
There is no such provisioning in C#.
However I would name private variables differently (e.g. m_something or just _something) so it is easier to spot it when it is used.
You can put all of your private fields into a nested class and expose them via public properties. Then within your class, you instantiate that nested class and use it. This way those private fields are not accessible as they would have been if they were part of your main class.
public class A
{
class FieldsForA
{
private int number;
public int Number
{
get
{
//TODO: Extra logic.
return number;
}
set
{
//TODO: Extra logic.
number = value;
}
}
}
FieldsForA fields = new FieldsForA();
public int Number
{
get{ return fields.Number;}
set{ fields.Number = value;}
}
}
It just provides a level of obstruction. The underlying problem of accessing private backing fields is still there within the nested class. However, the code within class A can't access those private fields of nested class FieldForA. It has to go through the public properties.
Perhaps a property backing store, similar to the way WPF stores properties?
So, you could have:
Dictionary<string,object> mPropertyBackingStore = new Dictionary<string,object> ();
public PropertyThing MyPropertyThing
{
get { return mPropertyBackingStore["MyPropertyThing"] as PropertyThing; }
set { mPropertyBackingStore["MyPropertyThing"] = value; }
}
You can do all the pre-processing you want now, safe in the knowledge that if anyone did access the variable directly, it would have been really really hard compared to the property accessor.
P.S. You may even be able to use the dependency property infrastructure from WPF...
P.P.S. This is obviously going to incur the cost of casting, but it depends on your needs - if performance is critical, perhaps this isn't the solution for you.
P.P.P.S Don't forget to initialise the backing store! (;
EDIT:
In fact, if you change the value property stored to a property storage object (using the Command pattern for example), you could do your processing in the command object...just a thought.
Can't do this in standard C#, however you could
define a custom attribute say OnlyAccessFromProperty
write your code like
[OnlyAccessFromProperty(Name)]
String name
Name
{
get{return name;}
}
etc …
Then write a custom rule for FxCop (or another checker)
Add FxCop to your build system so if your custom rule find an error the build is failed.
Do we need a set of standard custom rules/attributes to enforce common design patens like this without the need to extend C#
C# has no language feature for this. However, you can rely on naming conventions, similar to languages which have no private properties at all. Prefix your more private variable names with _p_, and you'll be pretty sure that you don't type it accidentally.
I don't know C# but in Java you may have a base class with only private instance variables and public setters and getters (should return a copy of the instance var.) and do all other in an inherited class.
A "general design principle" would be "use inheritance".
There is no build in solution in C#, but I think your problem can be solved by good OO design:
Each class should have a single purpose. So try to extract the logic around your field into a class as small as possible. This reduces the code where you can access the field by accident. If you do such errors by accident, your class is probably to big.
Often interface are good to restrict access to only a certain "subset" of an object. If that's appropriate for your case depends on your setting of course. More details about the work to be done would help to provide a better answer.
You say that you do additional processing. Presumably this would be detectable under the correct conditions. My solution, then, would be to create unit tests that implement conditions such that if the backing field is used directly the test will fail. Using these tests you should be able to ensure that your code correctly uses the property interface as long as the tests pass.
This has the benefit that you don't need to compromise your design. You get the safety of the unit tests to ensure that you don't accidently make breaking changes and you capture the understanding of how the class works so that others who come along later can read your tests as "documentation."
Wrap it in a class? The property thing is a bit like that anyway, associating data with methods - the "Encapsulation" they used to rave about...
class MyInt
{
private int n;
public static implicit operator MyInt(int v) // Set
{
MyInt tmp = new MyInt();
tmp.n = v;
return tmp;
}
public static implicit operator int(MyInt v) // Get
{
return v.n;
}
}
class MyClass
{
private MyInt myint;
public void func()
{
myint = 5;
myint.n = 2; // Can't do this.
myint = myint + 5 * 4; // Works just like an int.
}
}
I'm sure I'm missing something? It seems too normal...
BTW I do like the closures one, superbly mad.
My favorite solution to this (and what I follow) is to name private backing fields that are never intended to be used directly with a leading underscore, and private fields that are intended to be used without the underscore (but still lowercase).
I hate typing the underscore, so if I ever start to access a variable that starts with the underscore, I know somethings wrong - I'm not supposed to be directly accessing that variable. Obviously, this approach still doesn't ultimately stop you from accessing that field, but as you can see from the other answers, any approach that does is a work around and/or hardly practical.
Another benefit of using the underscore notation is that when you use the dropdown box to browse your class, it puts all of your private, never-to-be-used backing fields all in one place at the top of the list, instead of allowing them to be mixed in with their respective properties.
As a design practice, you could use a naming convention for "private properties" that's different from normal public members - for instance, using m_ItemName for private items instead of ItemName for public ones.
If you're using the C# 3.0 compiler you can define properties which have compiler-generated backing fields like this:
public int MyInt { get; set; }
That will mean there is only one way to access the property, sure it doesn't mean you can only access the field but it does mean that there's nothing but the property to access.
I agree with the general rule that the class should trust itself (and by inference anybody coding within the class).
It is a shame that the field is exposed via intellisense.
Sadly placing [EditorBrowsable(EditorBrowsableState.Never)] does not work within that class (or indeed the assembly(1))
In Visual C#, EditorBrowsableAttribute does not suppress members from a class in the same assembly.
If you really do wish to solve this aspect of it the the following class may be useful and makes the intent clear as well.
public sealed class TriggerField<T>
{
private T data;
///<summary>raised *after* the value changes, (old, new)</summary>
public event Action<T,T> OnSet;
public TriggerField() { }
///<summary>the initial value does NOT trigger the onSet</summary>
public TriggerField(T initial) { this.data=initial; }
public TriggerField(Action<T,T> onSet) { this.OnSet += onSet; }
///<summary>the initial value does NOT trigger the onSet</summary>
public TriggerField(Action<T,T> onSet, T initial) : this(onSet)
{
this.data=initial;
}
public T Value
{
get { return this.data;}
set
{
var old = this.data;
this.data = value;
if (this.OnSet != null)
this.OnSet(old, value);
}
}
}
Allowing you to (somewhat verbosely) use it like so:
public class Foo
{
private readonly TriggerField<string> flibble = new TriggerField<string>();
private int versionCount = 0;
public Foo()
{
flibble.OnSet += (old,current) => this.versionCount++;
}
public string Flibble
{
get { return this.flibble.Value; }
set { this.flibble.Value = value; }
}
}
alternatively you can go for a less verbose option but accessing Flibble is by the not idiomatic bar.Flibble.Value = "x"; which would be problematic in reflective scenarios
public class Bar
{
public readonly TriggerField<string> Flibble;
private int versionCount = 0;
public Bar()
{
Flibble = new TriggerField<string>((old,current) => this.versionCount++);
}
}
or solution if you look at the community content!
The new Lazy class in .net 4.0
provides support for several common
patterns of lazy initialization
In my experience this is the most common reason I wish to wrap a field in a private properly, so solves a common case nicely. (If you are not using .Net 4 yet you can just create your own “Lazy” class with the same API as the .Net 4 version.)
See this and this and this for details of using the Lazy class.
Use the "veryprivate" construct type
Example:
veryprivate void YourMethod()
{
// code here
}

Should I use a Field or Property within the class to set values

So I got into a friendly argument with a co-worker over a piece of code:
public sealed class NewObject
{
private string _stuff = string.Empty;
public string Stuff
{
get { return GetAllStuff(); }
}
private string GetAllStuff()
{
//Heavy string manipulation of _stuff
}
public NewObject(string stuffToStartWith)
{
_stuff = stuffToStartWith;
}
public static NewObject operator +(NewObject obj1, NewObject obj2)
{
if (obj1 == null)
throw new ArgumentNullException();
if (obj2 == null)
throw new ArgumentNullException();
NewObject result = new NewObject(string.Empty);
result._stuff = String.Concat(obj1._stuff, obj2._stuff);
return result;
}
}
The argument was over the operator override. My co-worker feels that it's not best programming practice to set values of private fields anywhere but the constructor. The solution proposed by my co-worker was to refactor the name of the Stuff property to AllStuff and add a property, Stuff, that has a get AND set accessor and use the new Stuff property in the operator override. Making it look like this:
public static NewObject operator +(NewObject obj1, NewObject obj2)
{
if (obj1 == null)
throw new ArgumentNullException();
if (obj2 == null)
throw new ArgumentNullException();
NewObject result = new NewObject(string.Empty);
result.Stuff = String.Concat(obj1.Stuff, obj2.Stuff);
return result;
}
I disagree. I feel the first way is better since it keeps the property read-only outside the class. My question is, which way is the best practice for object-oriented design?
You could give yourself a private set on the property (which would retain visibility or lack thereof while allowing you to use property syntax), but that doesn't really address the point.
Within the class, I say that variables are fair game. Anywhere outside, including inherited classes, should get and set the property, but within the declaring class I say it's OK to assign the private member.
The general issue has to do with a contract policy.
The notion of a (public set) property is that when it is called, other actions may be taken in addition to the semantic notion of changing state. For example, calling a setter may fire events, trigger a peripheral device and so on.
Your coworker is saying that by not using the property, you're side-stepping the contract and no events will be fired.
So here's you should do from your coworker's point of view:
this.Prop = CalculateSomeValue();
if (this.Prop < kPropMin) {
this.Prop = kPropMin;
}
else if (this.Prop > kPropMax * 2) {
this.Prop = kPropMax * 2;
}
this.Prop = this.Prop / 2;
Now, this is a contrived case, but I've just hit a possible heavyweight property up to three times in the get and up to three times in the set, and one of those might be illegal (setting to kHighLimit / 2). I can work around this by using a local and calling the set precisely once at the end. I'd rather just mess with the field, though.
I think a better approach is to take it pragmatically: use the property inside your class if and only if you want to invoke all the side-effects of a set or a get, otherwise obey the spirit of the property instead.
-- clarification --
By obey the spirit of the property, let's say that my set property looks like this:
bool PropValueOutOfRange(int val) {
return val < kPropMin || val > kPropMax;
}
public int Prop {
set {
if (PropValueOutOfRange(value))
throw new ArgumentOutOfRangeException("value");
if (PropValueConflictsWithInternalState(value))
throw new ArgumentException("value");
_prop = value;
NotifyPeriperalOfPropChange(_prop);
FirePropChangedEvent(/* whatever args might be needed */);
}
}
In this I've factored out a lot of the grungy details, but that lets me reuse them. So now I feel confident in touching the private field _prop because I have the same infrastructure for making sure that I keep it in range and to notify the peripheral and fire the event.
This lets me write this code:
_prop = CalculateSomeValue();
if (_prop < kPropMin)
_prop = kPropMin;
else if (_prop > kPropMax * 2)
_prop = kPropMax;
_prop /= 2;
NotifyPeripheralOfPropChange();
FirePropChangedEvent();
I'm using the same tools as those used to build the property so I'm working within the spirit of the property. I maintain correct range (but don't throw - I know better, I'm the implementer), hit the peripheral and fire events, and I do it thoughtfully, readably, and efficiently - not indiscriminately.
You're right
err... to elaborate, your private variables are yours to do as you please. If someone does an operation on you that changes the value of the object, (especially something like +), theres nothing wrong with modifying the value outside of the constructor. Thats the whole point of them being private.
Unless you want it immutable...
Update
The more i think about it, the more I believe your co-worker is confusing 'private' variables with 'constant' ones - or perhaps merging the two concepts. There is no reason that private variables have to remain the same throughout the life of the object, which is what your friend seems to be implying. const is for unchanging, private is for the object only, they are two very distinct patterns.
Update2
Also, his design falls apart if suddenly your object has more than just a string - and the variables are intertwined (think of a string object, that has a char* and a len, and must be maintained together). The last thing you want is for the user to have to deal with internal variables of an object. Let the object be an object and maintain its own internal values and present a single entity to the user.
I don't see what the benefit of his approach would be.
I personaly prefer to have no fields at all, hence I use auto-implemented private properties instead of private fields and public-get private-set properties if want to have public read-only properties.
If I have to add code to the property, I still only use the field inside of the property accessors and use the getters and setters everywhere else including the constructor.
I have to use fields, too, if I need readonly fields, but C# 4.0 will introduce read-only properties.
Further I would have avoided the whole problem by using the following code.
public static NewObject operator +(NewObject obj1, NewObject obj2)
{
return new NewObject(String.Concat(obj1.Stuff, obj2.Stuff));
}
My prefered implementation would be something like this.
public sealed class NewObject
{
private String Stuff { get; set; }
// Use a method instead of a property because the operation is heavy.
public String GetAllStuff()
{
// Heavy string manipulation of this.Stuff.
return this.Stuff;
}
// Or lets use a property because this.GetAllStuff() is not to heavy.
public String AllStuff
{
get { return this.GetAllStuff(); }
}
public NewObject(String stuffToStartWith)
{
this.Stuff = stuffToStartWith;
}
public static NewObject operator +(NewObject obj1, NewObject obj2)
{
// Error handling goes here.
return new NewObject(String.Concat(obj1.Stuff, obj2.Stuff);
}
}

Categories

Resources