Am I misunderstanding something about pass by reference?
SomeClass is the IObserver implementer:
bool value = false;
provider.Subscribe(new SomeClass(ref value));
while (!value)
{
provider.GetEvents() //triggers OnNext
}
In SomeClass:
public SomeClass(ref bool value)
{
this.value = value;
}
public void OnNext(object someUpdatedValue)
{
value = true;
}
Value never becomes true and the while loop never breaks. How come? Does assigning the value property of SomeClass to the reference of value not persist?
Edit: After seeing the first two responses my new question is this:
How can I achieve this kind of behavior without using static variables?
Pass by reference affects only the variable passed as the argument to the method. In your example, the value of false, which is what the variable value contained when you assigned it to this.value, is copied to the this.value field. Nothing more.
There's nothing magical in C# that will remember where that value came from and update the variable later, when the field to which its value was assigned is changed later.
Does assigning the value property of SomeClass to the reference of value not persist?
You aren't assigning "the reference of value". All that happens when you pass by-reference is that if the local variable itself is changed, then the variable that was passed is modified. When you use the value of the variable, you're only using the value, not the reference.
EDIT:
Without more context, it's impossible to say what the best way to approach this would be. But note that reference types achieve something similar to what you seem to be trying to do. For example:
class VolatileBoolWrapper
{
public bool Value { get { return _value; } }
private volatile bool _value;
public void SetValue(bool value)
{
_value = value;
}
}
VolatileBoolWrapper value = new VolatileBoolWrapper();
provider.Subscribe(new SomeClass(value));
while (!value.Value)
{
provider.GetEvents() //triggers OnNext
}
public SomeClass(VolatileBoolWrapper value)
{
this.value = value;
}
public void OnNext(object someUpdatedValue)
{
value.SetValue(true);
}
In that way, the VolatileBoolWrapper class acts as a go-between for the caller and callee.
<edit>
Note that I marked the field as volatile, and named the class Volatile... just to be safe. There's not enough context in the question for me to know what "triggers" actually means (i.e. does the same thread actually set the value, or is this something that involves interaction between threads).
If it happens that the call to OnNext() occurs within the same thread, strictly by virtue of the call to GetEvents(), then you can omit the use of volatile here (and ignore, or at least discount, my note about polling below).
</edit>
All that said, frankly: polling on a variable like this is pretty much always the wrong way to accomplish one's goals. There have always been much better approaches for things like this, but in modern C#, I would say that TaskCompletionSource is the best alternative. Like other mechanisms that came before it, it allows your waiting code to not continually use CPU time checking to see if the event has occurred; unlike them, it also provides an excellent mechanism for allowing that entire thread to continue executing, performing other work, only resuming at the await statement where you waited for the event when that event actually occurs.
The ref modifier affects the caller, not the callee. It allows you to reassign the caller's variable to "point to" a new value. For example:
bool myValue = true;
WithoutRef_YouCannotReassign(myValue);
Console.WriteLine(myValue); // myValue is still true
WithRef_YouCanReassign(ref myValue);
Console.WriteLine(myValue); // myValue is now false
void WithoutRef_YouCannotReassign(bool value) {
value = false;
}
void WithRef_YouCanReassign(bool value) {
value = false;
}
You're trying to pass out a reference to SomeClass.value. Normally, that'd work great by just swapping your assignment (remember, you're changing the caller's variable to point at something else)
public SomeClass(ref bool value)
{
value = this.value;
}
But, you've got another problem. Since a bool is immutable - even though your caller is pointing at the right value, you point your own value to something else later by overwriting it:
public void OnNext(object someUpdatedValue)
{
value = true; // value is now pointing somewhere else! the caller never got a reference to the somewhere else!
}
So, now, you actually need a wrapper to avoid having to overwrite SomeClass.value after you passed a reference out to it:
struct MyBoolWrapper
{
public bool Value { get; set; }
}
public SomeClass(ref MyBoolWrapper value)
{
value = this.value;
}
public void OnNext(object someUpdatedValue)
{
value.Value = true;
}
Now, this won't work because it's a struct (like bool is). structs are value types, and so the value of it gets copied back. When you change SomeClass.value, you're changing a different copy again! (This is one reason we tend to prefer immutable structs, like bool is).
So, let's change this to a class:
class MyBoolWrapper
{
public bool Value { get; set; }
}
This will work as expected since you end up passing back a reference to MyBoolWrapper (which doesn't change).
So, now we're working - but let's look at some cleanup. It seems a little silly for our caller to have to new a MyBoolWrapper just so that we can point it to something else. Let's change that:
MyBoolWrapper wrapper = null;
provider.Subscribe(new SomeClass(ref wrapper));
Well, now it seems silly that we set it to null. Since SomeClass is providing all the info, let's just make it an out (which, essentially, works the same as ref just without requiring it to be initialized):
MyBoolWrapper wrapper;;
provider.Subscribe(new SomeClass(out wrapper));
Of course, now it's not even clear why we can't just hold a reference to SomeClass directly, and get rid of this whole out/ref dance:
SomeClass someClass = new SomeClass();
provider.Subscribe(someClass);
while (!someClass.Value) {
provider.GetEvents();
}
class SomeClass {
public Value { get; private set; }
public void OnNext(object someUpdatedValue)
{
Value = true;
}
}
There - that's simpler. Since the caller has a reference to our instance that changes it's state (without changing it's identity), we don't have to worry about all of that method calling by-ref/by-val struct vs class mumbo-jumbo.
Related
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.
I understand struct is value type. But I do not understand why it behave like this?
Is it because i didn't treat it as immutable? or is it has something to do with the auto property?
using System;
namespace StructQuestion
{
class Program
{
static StructType structAsProperty { get; set; }
static StructType structAsField;
static void Main(string[] args)
{
structAsProperty.InjectValue("structAsProperty");
structAsField.InjectValue("structAsField");
//debugger says structAsProperty.GetValue() is null
Console.WriteLine(structAsProperty.GetValue());
Console.WriteLine(structAsField.GetValue());
Console.ReadLine();
}
}
public struct StructType
{
private string value;
public void InjectValue(string _value)
{
value = _value;
}
public string GetValue()
{
return value;
}
}
}
Let's look at what happens in this statement:
structAsProperty.InjectValue("structAsProperty");
We don't have to go far. The very first thing that must happen is to resolve the structAsProperty part of the statement. The key here is understanding the compiler re-writes property get and set sections as a method calls behind the scenes.
So what we really have here is a call to a method that returns our struct value. I say "value" here rather than "object" because structs are value types. With value types, passing to or returning from a method results in a copy of the value.
Now we know enough to understand what happened. We are calling InjectValue() on a copy of the property struct, not the instance in the property itself. Next we modify this copy via it's InjectValue() method... and then promptly forget the copy ever existed.
You can fix it like this:
var prop = structAsProperty; //now we have a variable to keep the result of the implicit get accessor method
prop.InjectValue("structAsProperty");
structAsProperty = prop;
This might be a trivial question but I got really confused on this. I have a property with some logic in it.
private SomeObject _someProperty;
public SomeObject SomeProperty
{
get
{
Some checking here,
return _someProperty;
}
set
{
_someProperty = value;
}
}
Now what will happen when I am going to assign something to this property.
SomeProperty = new SomeClass();
What I was thinking here that get will be called here. It words it can be said like get SomeProperty and set that property. But what I have observed is that get is not called. Only setter is called (correct me if I am wrong here). I want to know if get is not called here what is its reason.
In simpler way to think about it.
GET: When something somewhere wants to GET value from here.
SET: When something somewhere wants to SET value here.
So, getters and setters answer to question from outside perspective. When you want to write value, SET is called. When you want to know current value, GET is called.
Properties are really just syntactic sugar for get/set methods. As the C# Programming Guide says:
A property is a member that provides a flexible mechanism to read, write, or compute the value of a private field. Properties can be used as if they are public data members, but they are actually special methods called accessors. This enables data to be accessed easily and still helps promote the safety and flexibility of methods.
So your example really translates to something like:
private SomeObject _someProperty;
public SomeObject get_SomeProperty()
{
// Some checking here,
return _someProperty;
}
public void set_SomeProperty(SomeObject value)
{
_someProperty = value;
}
With the assignment becoming
set_SomeProperty(new SomeClass());
When thought of this way, it's clear that the getter is not called when you assign the property.
No, a property's getter is not called when setting the property, as can be easily demonstrated :
static class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
foo.Number = 7;
}
}
public class Foo
{
private int number;
public int Number
{
get
{
Console.WriteLine("In getter");
return this.number;
}
set
{
Console.WriteLine("In setter");
this.number = value;
}
}
}
Output:
In setter
No, get is called when you are reading the value of the property, set is called when you are assigning a value to the property.
What I was thinking here that get will be called here
Why? You are clear - you SET. And SET does not do anything in GET. Ergo, get is never called.
This IS the correct behaviour of mutator methods, you dont Read the Value from accessor
You don't need value of SomeProperty in this expression. If you wrote something like SomeProperty = SomeProperty + 1; then you will need a value of SomeProperty, and get will be called.
Actually
A property is a member that provides a flexible mechanism to read,
write, or compute the value of a private field. Properties can be used
as if they are public data members, but they are actually special
methods called accessors.
as it is said in msdn.
So consider it as a wrapper for something like this:
private SomeObject _someProperty;
public SomeObject getSomeProperty()
{
//Some checking here,
return _someProperty;
}
public void setSomeProperty(SomeObject value)
{
_someProperty = value;
}
It should be clear now unless you have the same question about setting the fields.
This might be a dumb question, but the property below, will there ever be a situation where just getting it will cause an exception?
Like if I did something like bool value = this.BatchValuation; - but I hadn't set BatchValuation yet, will it just set value to null, or will it cause an exception?
public bool BatchValuation { get; set; }
This might be a dumb question
It is not.
in the property below, will there ever be a situation where just getting it will cause an exception?
Possibly, yes. For example, another thread could abort your thread while it was in the middle of fetching that property; that would appear to be an exception thrown by the property getter. Or, you could run out of stack space right at the moment where the property is called, and an out-of-stack exception could be thrown. Or, when you call the property for the first time, the jitter might start up and try to allocate virtual memory for the generated code, but you are all out of virtual address space, so an out of memory exception could be thrown.
Those are all extraordinarily unlikely, but they are all possible. You asked if there would ever be such a situation, not if it was likely.
If I hadn't set BatchValuation yet, will it just set value to null, or will it cause an exception?
Neither; it will default to false. Booleans are not nullable.
boolean values default to false if you have not set them specifically. So no there will be no exception, the property will just return false.
Remember that this is a value type we are talking about, only variables for reference types can be set to null. Value types do have a default value, which is zero for numeric types and false for boolean.
Also see Default Values Table
no, Boolean defaults to false. So
bool something; // something is false
In the context of class properties or member fields, each field is initialized to a default value for the type when the class is created prior to the constructor being run. In the class
class Foo
{
bool bar;
string s;
int item;
public double Baz { get; set; }
}
The first three fields are set to their initial values (false, null, and 0, respectively), and the auto-generated backing field for Baz is also set to 0.0d. It is not an error to access these fields/properties without explicit user-initialization, unlike accessing uninitialized locals. It is for locals that the compiler requires explicit initialization.
class Foo
{
int bar;
void M()
{
Console.WriteLine(bar); // not an error, bar is 0;
bool someBool;
Console.WriteLine(someBool); // use of uninitialized local variable
}
}
As BrokenGlass said, the boolean values default to false,
you can test it by yourself, I provide a sample as below.
static void Main()
{
// Create an object, but don't set attribute.
Foo foo = new Foo();
if (!foo.BatchValuation)
Console.WriteLine("BatchValuation is False");
else
Console.WriteLine("BatchValuation is True");
Console.ReadKey();
}
}
// Test class.
public class Foo
{
private bool _batchValuation;
public Foo() { }
public bool BatchValuation
{
get { return _batchValuation; }
set { _batchValuation = value; }
}
}
Once I had a very weird situation, when auto-implemented property like this threw a NullReferenceException exception. The reason was Emit Mappper library (http://emitmapper.codeplex.com/).
This library (which is very good otherwise) uses Refleciton.Emit and, when it sees no public constructor for the type, it emits mapping call sites, which pass null reference as implied first argument of property/method (which ends up as "this" in all instance methods).
So the property was trying to change field value of a null reference (that is, I had this==null situation)!
The C# "readonly" keyword is a modifier that when a field declaration includes it, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.
Now suppose I do want this "assign value once" constraint, but I would rather allow the assignment be done outside of constructors, a lazy/late evaluation/initialization maybe.
How could I do that? and is it possible to do it in a nice way, for example, is it possible to write some attribute to describe this?
If I understand your question correctly, it sounds like you just want to set a field's value once (the first time), and not allow it to be set after that. If that is so, then all the previous posts about using Lazy (and related) may be useful. But if you don't want to use those suggestions, perhaps you can do something like this:
public class SetOnce<T>
{
private T mySetOnceField;
private bool isSet;
// used to determine if the value for
// this SetOnce object has already been set.
public bool IsSet
{
get { return isSet; }
}
// return true if this is the initial set,
// return false if this is after the initial set.
// alternatively, you could make it be a void method
// which would throw an exception upon any invocation after the first.
public bool SetValue(T value)
{
// or you can make thread-safe with a lock..
if (IsSet)
{
return false; // or throw exception.
}
else
{
mySetOnceField = value;
return isSet = true;
}
}
public T GetValue()
{
// returns default value of T if not set.
// Or, check if not IsSet, throw exception.
return mySetOnceField;
}
} // end SetOnce
public class MyClass
{
private SetOnce<int> myReadonlyField = new SetOnce<int>();
public void DoSomething(int number)
{
// say this is where u want to FIRST set ur 'field'...
// u could check if it's been set before by it's return value (or catching the exception).
if (myReadOnlyField.SetValue(number))
{
// we just now initialized it for the first time...
// u could use the value: int myNumber = myReadOnlyField.GetValue();
}
else
{
// field has already been set before...
}
} // end DoSomething
} // end MyClass
Now suppose I do want this "assign value once" constraint, but I would rather allow the assignment be done outside of constructors
Note that lazy initialization is complicated, so for all of these answers you should be careful if you have multiple threads trying to access your object.
If you want to do this inside the class
You can use the C# 4.0 built-in lazy initialization features:
http://msdn.microsoft.com/en-us/library/dd997286.aspx
http://msdn.microsoft.com/en-us/library/dd642331.aspx
http://sankarsan.wordpress.com/2009/10/04/laziness-in-c-4-0-lazyt/
Or for older versions of C#, just supply a get method, and check if you're already initialized by using a backing field:
public string SomeValue
{
get
{
// Note: Not thread safe...
if(someValue == null)
{
someValue = InitializeSomeValue(); // Todo: Implement
}
return someValue;
}
}
If you want to do this outside the class
You want Popsicle Immutability:
http://blogs.msdn.com/b/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx
http://msdn.microsoft.com/en-us/library/ms750509.aspx
http://csharpindepth.com/Talks.aspx (search for "popsicle immutability" and you'll find a video)
Basically:
You make the whole class writable, but add a Freeze method.
Once this freeze method is called, if users try to call setters or mutator methods on your class, you throw a ModifyFrozenObjectException.
You probably want a way for external classes to determine if your class IsFrozen.
BTW, I made up these names just now. My selections are admittedly poor, but there is no generically followed convention for this yet.
For now I'd recommend you create an IFreezable interface, and possibly related exceptions, so you don't have to depend on the WPF implementation. Something like:
public interface IFreezable
{
void Freeze();
bool IsFrozen { get; }
}
You can use the Lazy<T> class:
private readonly Lazy<Foo> _foo = new Lazy<Foo>(GetFoo);
public Foo Foo
{
get { return _foo.Value; }
}
private static Foo GetFoo()
{
// somehow create a Foo...
}
GetFoo will only be called the first time you call the Foo property.
This is know as the "once" feature in Eiffel. It is a major oversight in C#. The new Lazy type is a poor substitute since it is not interchangeable with its non-lazy version but instead requires you to access the contained value through its Value property. Consequently, I rarely use it. Noise is one of the biggest problems with C# code. Ideally, one wants something like this...
public once Type PropertyName { get { /* generate and return value */ } }
as oppose to the current best practice...
Type _PropertyName; //where type is a class or nullable structure
public Type PropertyName
{
get
{
if (_PropertyName == null)
_PropertyName = /* generate and return value */
return _PropertyName
}
}