get a property's private setter within inheritance - c#

following are my codes:
class Foo
{
public string Bar { get; private set; }
}
and
var prop = typeof(Foo).GetProperty("Bar");
if (prop != null)
{
// The property exists
var setter = prop.GetSetMethod(true);
if (setter != null)
{
// There's a setter
Console.WriteLine(setter.IsPublic);
}
}
yes, as you can imagine, this works perfectly right. but when there comes a inheritance, things are different:
class Foo
{
public string Bar { get; private set; }
}
class A : Foo
{
}
of course i changed this line:
var prop = typeof(Foo).GetProperty("Bar");
to
var prop = typeof(A).GetProperty("Bar");
then, the setter gets to null, and console print nothing!
so...why?
btw, is there some workaround to make this happen or totally another way to?
any help would be appreciated. thanks.

The general solution is to call
var prop = GetType().GetProperty("Bar").DeclaringType.GetProperty("Bar");
Which is not very intuitive, i agree.

so...why?
As far as A is concerned, Bar is read-only - you can't call the setter from A, so it does make sense that there's no setter when you ask for the property with respect to A.
One alternative is to use binding flags to only ask for declared properties - and walk your way up the inheritance chain until you find the actual property declaration. It's a little bit odd that you have to do this, but it does make a certain amount of sense, as the property really is different depending on whether you're coming to it from the context of the declaring class or not.
I'm surprised by this behaviour - but not shocked.

You can set the private property with reflection by just using the SetValue method in the property info, even if you can't get the set method.

Related

Is "get" called when we call "set" for a property

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.

Are the property getters evaluated as soon as the property container class is loaded / instantiated into the memory?

I have a simple question. I designed a C# class where I got some property getters who are responsible for doing some performance expensive tasks. I have many properties like that in my class. My question, are those property getters are evaluated as soon as the the instance of the class is loaded into the memory ? If so, then, I will consider breaking them into methods. I hope they evaluated only when the property is used for the first time, but I need to be sure about it about this assumption.
I know I should use methods for expensive tasks, but I just found using Properties are more maintainable where I have many many members in a class.
Thanks.
Property getters/setters are evaluated for every call to/from them. They are nothing more than syntactic for methods.
public class Foo
{
private int actual = 0;
public int Bar
{
get { return actual++; }
set { value = actual; value++ }
}
}
int v = foo.Bar; //0
v = foo.Bar; // 1
v = foo.Bar; // 2
foo.Bar = v; // actual = 3
Property getters are not for instantiation, since getters/setters only run when you call the property. Use the constructor for instantiating properties. The exception to this rule is lazy initialization, when a (usually readonly) property's value is initialized the first time it is accessed.
No, they will not be evaluated when the class is instantiated. They will only be evaluated when they are accessed (and every time thereafter). This allows you to implementat "lazy-loading". It may be wise (depending on your situation) to save the result in a private field after evaluating once, and returning that result for every subsequent call.
private string foo;
public string Foo
{
get
{
if (foo == null)
foo = "expensive operation";
return foo;
}
}
Getters/setters are evaluated when you do call them. Consider this:
private string sample;
public string Sample
{
get
{
return (sample = sample ?? SomeExpensiveMethod());
}
}
This way you can control when to call your expensive method.
Also consider static properties are populated only once in your application lifetime. So that can also be a choice, depending on your scenario.
It's worth mentioning that you can also evaluate the value to be assigned by using the keyword "value". for example:
public String Author
{
get { return author; }
set
{
if (value.Equals(""))
Console.WriteLine();
else
author = value;
}
}
This way, you can evaluate the assignement.

Is it right to have a setter to set different type than the property type?

e.g.
[XmlAttribute("Type")]
public string DataTypeString
{
get
{
return _dataType.ToString();
}
set
{
_dataType = Type.GetType(value);
}
}
private Type _dataType;
public Type DataType
{
get { return _dataType; }
set { _dataType = value; }
}
In the above code, first property type is string, however the setter sets, the _dataType which is of System.Type
You can and often benificial to do so for get properties.
Type conversion in set properties likley be more contraversial. Properties are normally expected to be lightweight, not to throw exceptions and normally x.YYY=newValue; expected to result in x.YYY==newValue to be true - these may be hard to achieve if type conversion happens.
I.e. in your particular example allowing to set type by string as property feels like a bad idea - what is expected behavior of x.DataTypeString="42";? You may want to consider some other way to enable XML serialization of your property...
Sure you can. That's the purpose of the properties. The user of the property doesn't need to know what's behind it. He/she just sets or gets a string and that's all they need to know.
I guess its ok, but I would prefer to just do this, which less odd and less verbose:
public void SetDataType(string value) {
_dataType = Type.GetType(value);
}
public void SetDataType(Type value) {
_dataType = value;
}
public Type DataType { get; private set; }
As was already mentioned, it seems rather odd to have two getter/setter pairs for the same private variable.
It's hard to say without knowing the purpose of this class. But in general, I think I'd be confused by having two properties with the same backing field (so that changing one affects the other).
There are exceptions though. For example, in a Circle class, I would find it perfectly reasonable to have both a Radius property and a Diameter property. So again, it kind of depends on the purpose of your class.
Also, in the example you provided, it doesn't seem like the DataTypeString property provides much benefit. If you remove it, callers could achieve the same effect by simply calling
foo.DataType = Type.GetType("System.Int32");
or
string dataTypeString = foo.DataType.ToString()
.

Get default value of class member

Let's assume I have a class ClassWithMember
class ClassWithMember
{
int myIntMember = 10;
}
How do I get the default value 10 of the myIntMember member by System.Type?
I'm currently struggling around with reflections by all I retreive is the default value of int (0) not the classes default member (10)..
You can try something like this:
var field = typeof(ClassWithMember).GetField("myIntMember",
BindingFlags.Instance | BindingFlags.NonPublic);
var value = (int)field.GetValue(new ClassWithMember());
The trick here is to instantiate an instance.
Try creating an instance an retreive the value with reflection.
If you're in control of the code for ClassWithMember, you could take a completely different approach to this by using the [DefaultValue] attribute from System.ComponentModel. Basically, what you'd do is write something like this:
class ClassWithMember
{
public ClassWithMember()
{
SetDefaultValues();
}
[DefaultValue(5)]
public MyIntMember { get; set; }
}
And then have a function like this somewhere, perhaps in a base class:
public void SetDefaultValues()
{
foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(this))
{
DefaultValueAttribute a = prop.Attributes[typeof(DefaultValueAttribute)] as DefaultValueAttribute;
if (a == null)
continue;
prop.SetValue(this, a.Value);
}
}
So now, you have a situation where you can easily retrieve the default values using Reflection.
Keep in mind that this is going to be quite a lot slower due to the Reflection requirement, so if this code gets instantiated a lot, you'll probably want to find a different approach. Also, it won't work with non-value types, due to a limitation with the .NET Framework's attribute support.
You can still use Activator.CreateInstance to create a MonoBehaviour/ScriptableObject and check its values, if it's simply for the sake of checking the default Values. Make sure to use DestroyImmediate afterwards ;-)

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