This is more of an "is there a better way" question than a real problem.
When having a property that is only accessed in a base class:
private const bool isSomething = true;
I sometimes have to change this value in a project where I inherit from this class. But as it is a constant and used class-wide, I normally change the code in the base class to something like this:
private const bool isSomething = true;
protected virtual bool IsSomething{
get{
return isSomething;
}
}
And override the property in the subclass and create a new isSomething constant.
This creates a new field and an override and, in my opinion, is not nice style. Is there a better way to do this?
The value is a constant, and it will be constant in the complete project where I'm using it.
If you need to set the value based on which class you are in but don't want the value to change later, than const is not the right keyword. Instead, you can use readonly and require sub-classes to pass in a value to the constructor.
The readonly keyword is different from the const keyword. A const field can only be initialized at the declaration of the field. A readonly field can be initialized either at the declaration or in a constructor. Therefore, readonly fields can have different values depending on the constructor used. Also, while a const field is a compile-time constant, the readonly field can be used for runtime constants...
Source
Edit:
To summarize: You have a filed that is only accessed by the base class and the base class should never alter that value. In most cases, the default value is fine. However, there are some cases that arise when a subclass need to set it's own value that is different than the default.
class Base {
private readonly bool _isSomething;
public Base() : this(false) {}
protected Base(bool isSomething)
{
_isSomething = isSomething;
}
}
class Child {
public Child() : base(true) {}
}
This provides the same functionality as your suggested work-around. The value can not be changed and only a child class can provide a different value. It has an added benefit of not allow the child class invalidate the fact that the value is intended to be constant. The override method allows for this:
protected override bool IsSomething{
get{
return BOOLEAN_EXPRESSION;
}
}
I understand your idea of making it a static value (since we know every instance will use the same value), but that only makes things complicated as static items are not inherited.
Related
Given the following
class BaseClass
{
public int Property {get; protected set;}
}
class DerivedClass : BaseClass
{
public new int Property {get; set;} //Hides BaseClass.Property
public static DerivedClass Build()
{
var result = new DerivedClass
{
Property = 17;
//base.Property = 17; // this doesn't compile
}
//((BaseClass)result).Property = 17; // this doesn't compile
}
}
Is there any way to set BaseClass.Property from a static method inside the DerivedClass.
Reflection or Unsafe code is not what I want! I want a non hacky way of setting something which we do legally have access to, but I just can't work out how to set.
Here is how to access an overridden property from a static method of the class:
Add to the class a new property that accesses the base property:
private double BaseProperty { get => base.MyProperty; set => base.MyProperty = value; }
Use that new property from your static:
var result = new DerivedClass
{
BaseProperty = 17;
}
Here is a situation where the above technique is the cleanest solution I have found.
Consider XAML that refers to a BindableProperty, in a class library.
(In my case, the class library is Xamarin Forms.)
Without changing the property name, I want to decouple the base property (used by code compiled into the library) from the XAML-visible property (in my subclass).
The specific use is making text auto-fit, which X-Forms doesn't yet support.
The detail that is relevant here, is that I have the following BindableProperty declaration:
public new static readonly BindableProperty FontSizeProperty =
BindableProperty.Create("FontSize", typeof(double), typeof(AutofitLabel), -1.0,
propertyChanged: (BindableObject bindable, object oldValue, object newValue) => {
((AutofitLabel)bindable).BaseFontSize = (double)newValue;
});
which uses this private property:
private double BaseFontSize { get => base.FontSize; set => base.FontSize = value; }
What this accomplishes, is to initially set base.FontSize - which will be used by layout logic inside library's Label or other text-containing view - to the value set in XAML. Elsewhere in my subclass, I have logic that lowers base.FontSize as needed, once the available width/height are known.
This approach makes it possible to use the library without altering its source code, yet make it appear, to clients of my subclass, that auto-fitting is built-in.
It wouldn't be valid to change FontSize that is visible to client code - that represents the requested size. However, that is the approach taken by Charles Petzold in XF Book Ch. 5 "EmpiricalFontSizePage". Also, Petzold has the page itself deal with the auto-sizing - which is not convenient.
The challenge is the need to tell the library what actual FontSize to use.
Ergo this solution.
All other approaches I've found online require complex custom renderers, replicating logic already existing in XF library.
Is there any way to set BaseClass.Property from a static method inside the DerivedClass.
Yes, rethink your design. It is flawed. Hiding a property and then wanting to set the exact same value on the base and derived class? There seems something really wrong.
You don't necessarily need to hide the property, you could override it, but then it wouldn't make too much sense. It seems the only objective you have is to have different access modifiers on your base class and derived class. This goes against OOP rules, and should be avoided.
If you can introduce another intermediate class, then you can obviously do this. But as others have said, it doesn't just have a code smell, it's positively poisonous.
class BaseClass
{
public int Property { get; protected set; }
}
class InterClass : BaseClass
{
protected void DoFunnyStuff(int value)
{
this.Property = value;
}
}
class DerivedClass : InterClass
{
public new int Property { get; set; } //Hides BaseClass.Property
public static DerivedClass Build()
{
DerivedClass result = new DerivedClass
{
Property = 17
//base.Property = 17; // this doesn't compile
};
result.DoFunnyStuff(17);
return result;
//((BaseClass)result).Property = 17; // this doesn't compile
}
}
So DerivedClass does inherit from BaseClass still, but not directly. You can apply various tricks to try to minimize how much other code is exposed to the existence of InterClass.
It seems you want to modify the APIs behaviour in such a way that something which was mutable before should not be mutable any more. So why not defining a new property, which is really immutable and make the existing one Obsolete instead o trying to hide the original property but not hiding it?
class LegacyClass
{
[Obsolete("Use NewMember instead")]
public string ExistingMember { get; set; } // should actually be immutable
public string NewMember { get { ... } }
}
This way you donĀ“t break existing code.
Yes it's possible through reflection: Property hiding and reflection (C#)
No it's not possible in other ways, if you hide a property by design it's because you don't want give access to that from DerivedClass
Reflection allows you to access for particular purpose, it's not an hacky way the use of reflection.
It's an hacky way to access to a property that you have hidden by design.
If you want access in a legal way to a property you should not hide it.
Let say I have a class like this:
public class A
{
private BaseSettings fieldA;
public ISettings PropertyA
{
get {return fieldA;}
set {fieldA= value as BaseSettings;}
}
}
where BaseSettings implements ISettings. Inside class A, if I want to access BaseSettings' property called PropertyB, which of this is a good practice:
fieldA.PropertyB;
or
((BaseSettings)PropertyA).PropertyB;
One may say the first approach may hide the hint to when a property changed. For example, a code may listen to PropertyChangedEvent and then the value for property changed without raising the event.
Another one may say the second approach may expose a risk that when a person who is not familiar with current code modify it, he may cast the PropertyA to different type that implements ISettings.
Both approaches have its downside. In a good programming practice, which one should be more preferable?
EDIT:
Added based on the comments belows:
I agree that setting the backing-field as ISettings makes absolute sense. But what should I do to make sure that the PropertyA is always type of BaseSettings. That will raise a question: "Then why don't you set both property and backing-field to BaseSettings?".
The reason behind why property and its backing field are different is that class A also implement an interface like this
public interface IControlWithSettings
{
ISettings OwnerSettings
{
get;
set;
}
ISettings Settings
{
get;
set;
}
}
So the actual classA would look like this
public class BaseForm: Form, IControlWithSettings
{
private BaseFormSettings settings;
public ISettings Settings
{
get {return settings;}
set {settings= value as BaseFormSettings;}
}
}
And I have another class B would also implement IControlWithSettings
public class BaseUserControl: UserControl, IControlWithSettings
{
private BaseUserControlSettings settings;
public ISettings Settings
{
get {return settings;}
set {settings= value as BaseUserControlSettings ;}
}
}
Both BaseFormSettings : ISettings and BaseUserControlSettings : ISettings . This is actual ISettings interface
public interface ISettings
{
Dictionary<string, ISettings> Children { get; set; }
}
the 'as' casting is a side effect I put into the setter so that it will ignore and return null if the setting is set to wrong one. I read somewhere saying I shouldn't throw exception in a setter. So making it null is my way to inform there is something wrong has been done.
So what is the better approach. Did I design it wrong?
As you stated, both approaches have their downsides, and it also depends on whether the property setter may contain some additional logic (e.g. validation), and you may use or circumvent this additional logic from inside the class.
If there's nothing that speaks against it, I'll use direct access to the field. It's neater and it avoids all this typecasting stuff.
But generally: Why would you back your property with the derived type, while the property itself has the interface type? This doesn't make much sense. Why not just:
public class A
{
public ISettings PropertyA { get; set; }
}
This would be much cleaner, and your question wouldn't even arise.
Edit (based on the answer's edit)
In case of the 'double use' of the backing field the typecasting makes sense. But I don't think (and never heard that before) that it's a bad thing to throw an exception from a property setter. On the contrary: Validating a value and throwing an exception if it doesn't pass is a very common pattern.
So, in your concrete case, I would validate the value for the correct type, throw if it's not correct, and use the backing field internally to bypass this type check.
In almost all of my classes, I have a mixture of properties and internal class variables. I have always chosen one or the other by the rule "property if you need it externally, class variable if not". But there are many other issues which make me rethink this often, e.g.:
at some point I want to use an internal variable from outside the class, so I have to refactor it into a property which makes me wonder why I don't just make all my internal variables properties in case I have to access them externally anyway, since most classes are internal classes anyway it aren't exposed on an API so it doesn't really matter if the internal variables are accessible from outside the class or not
but then since C# doesn't allow you to instantiate e.g. List<string> property in the definition, then these properties have to be initialized in every possible constructor, so these variables I would rather have internal variables just to keep things cleaner in that they are all initialized in one place
C# code reads more cleanly if constructor/method parameters are camel case and you assign them to pascal case properties instead of the ambiguity of seeing templateIdCode and having to look around to see if it is a local variable, method parameter or internal class variable, e.g. it is easier when you see TemplateIdCode = templateIdCode that this is a parameter being assigned to a class property. This would be an argument for always using only properties on internal classes.
e.g.:
public class TextFile
{
private string templateIdCode;
private string absoluteTemplatePathAndFileName;
private string absoluteOutputDirectory;
private List<string> listItems = new List<string>();
public string Content { get; set; }
public List<string> ReportItems { get; set; }
public TextFile(string templateIdCode)
{
this.templateIdCode = templateIdCode;
ReportItems = new List<string>();
Initialize();
}
...
When creating internal (non-API) classes, what are your strategies in deciding if you should create an internal class variable or a property?
If I have a private variable that I find needs public access at a later point, I just create a property that uses it as it's private member, ex:
private List<string> listItems = new List<string>();
Public List<string> ListItems
{
get{return listItems;}
set{listItems = value;}
}
This allows you to create public access to the data, without having to refactor any code. It also allows you to initialize the data in the private member, and not have to do it in the constructor.
One more advantage is that any modifications to the data that you want to perform for anyone accessing the public property, can be done in the property's getter.
Even though VS2008 introduced Automatic Properties as a feature, I still prefer the VS2005 style of properties.
I've got a wrapper class which encapsulates a piece of information that needs to be transmitted as a byte array.
In that way, the class encapsulates the necessary header (with fields like DATA_LENGTH or MESSAGE_TYPE) into the corresponding byte positions. For that I want to define positions and length in constants, for example:
HEADER_DATA_LENGTH_IX = 0;
HEADER_DATA_LENGTH_LENGTH = 2;
which means DATA_LENGTH starts at 0 and takes two bytes.
but so far I'm struggling with making them constants or static readonly fields. Const cannot be protected, therefore I won't be able to derive a new class and change the constants if a use them, on the other way I might declare new constants in the derived class and the use them.
What will be your approach?
If you want to change the value of these params in a derived class, you can make them readonly and change them in the constructor of the derived class
I wouldn't make them const anyhow, because they're not...
The basic difference is when the variable is initialized. 'readonly' is set at initialization, or in the contructor, while 'const' is set at compile time.
I think the big decision is if you want to inherit the class and override the value. If you do, go readonly. Otherwise I don't think it really matters.
readonly C#ref: http://msdn.microsoft.com/en-us/library/acdd6hb7.aspx
const C# ref: http://msdn.microsoft.com/en-us/library/e6w8fe1b.aspx
Create an inner class with the constants. The deriving classes can then later override the inner class and change the constants as necessary.
e.g. base class:
public class Stuff
{
public class HeaderInformation
{
public const int HEADER_DATA_LENGTH_IX = 0;
public const int HEADER_DATA_LENGTH_LENGTH = 2;
}
}
Then the derived class can do this:
public class DerivedStuff : Stuff
{
public new class HeaderInformation : Stuff.HeaderInformation
{
public new const int HEADER_DATA_LENGTH_IX = 10;
}
}
This way, you have flexibility. In DerivedStuff, the HeaderInformation class has all of the constants in the base Stuff.HeaderInformation class, but can change any of them, or keep the ones it has.
This exact question is answered by the official c# faq on msdn
I wouldn't make these constant because they simply aren't constants. When declaring something as const you should ask yourself: can this change? Your message lengths might change one day, so they are better to be made readonly.
All I need is a way to make a property of one class only 'settable' from one other class (a sort of manager class).
Is this even possible in c#?
My colleague 'reliably' informs me that I have a design flaw, but I feel I should at least ask the community before I concede defeat!
No, it's not really possible to do this in any clean way in C#. You probably have a design flaw ;-)
You can use the internal modifier, which lets all types in the same assembly access the data (or nominated assemblies if using [InternalsVisibleTo] - but no: there is no friend equivalent in C#.
For example:
public string Foo {get; internal set;}
You have a design flaw. Also, don't be paranoid about data hiding. Here's 3.5's way to do it:
class Program
{
static void Main(string[] args)
{
Managed m = new Managed();
Console.WriteLine(m.PrivateSetter);
m.Mgr.SetProperty("lol");
Console.WriteLine(m.PrivateSetter);
Console.Read();
}
}
public class Managed
{
private Manager _mgr;
public Manager Mgr
{
get { return _mgr ?? (_mgr = new Manager(s => PrivateSetter = s)); }
}
public string PrivateSetter { get; private set; }
public Managed()
{
PrivateSetter = "Unset";
}
}
public class Manager
{
private Action<string> _setPrivateProperty;
public Manager(Action<string> setter)
{
_setPrivateProperty = setter;
}
public void SetProperty(string value)
{
_setPrivateProperty(value);
}
}
Here's how we'd do it in pre-lambda days:
public class Managed
{
private Manager _mgr;
public Manager Mgr
{
get { return _mgr ?? (_mgr = new Manager(this)); }
}
public string PrivateSetter { get; private set; }
public Managed()
{
PrivateSetter = "Unset";
}
public class Manager
{
public void SetProperty(string value)
{
m.PrivateSetter = value;
}
private Managed m;
public Manager(Managed man)
{
m = man;
}
}
}
The best way to do it would be:
/// <summary>
/// Gets or sets foo
/// <b>Setter should only be invoked by SomeClass</b>
/// </summary>
public Object Foo
{
get { return foo; }
set { foo = value; }
}
When you have some complex access or inheritance restriction, and enforcing it demands too much complexity in the code, sometimes the best way to do it is just properly commenting it.
Note however that you cannot rely on this if this restriction has some security implications, as you are depending on the goodwill of the developer that will use this code.
You cannot do that on that way, but you can access a property's setter method from a derived class, so you can use inheritance for the purpose. All you have to do is to place protected access modifier. If you try to do so, your colleague is right :). You can try doing it like this:
public string Name
{
get{ return _name; }
protected set { _name = value; }
}
keep in mind that the set method of the property is only accessible from the derived class.
Or you could have these two classes in an assembly alone and have the setter as internal. I would vote up for the design flaw though, unless the previous answer by milot (inheriting and protected) makes sense.
You could do:
public void setMyProperty(int value, Object caller)
{
if(caller is MyManagerClass)
{
MyProperty = value;
}
}
This would mean that you could use a 'this' pointer from the calling class. I would question the logic of what you're attempting to achieve, but without knowing the scenario I can't advise any futher. What I will say is this: if it is possible to refactor your code to make it clearer, then it is often worthwhile doing so.
But this is pretty messy and certinly NOT fool-proof ... you have been warned!
Alternativly...
You could pass a delegate from the Class with the Property (Class A) to the Manager Class (Class B). The delegate can refer to a private function within A to allow B to call that delegate as any normal function. This precludes that A knows about B and potentially that A is created before B. Again... messy and not fool-proof!
You can achieve to this by making a Public property in your "settable class" that will inherit from the real class that will have a protected property... this way only the inherit class can SET and not class that doesn't inherit. But the drawback is that you will require to have an inherit class...
Reflection, though I would agree that having to do this just to get around an access modifier is probably an indication of a bad design.
public class Widget
{
private int count;
public int Count
{
get { return this.count; }
private set { this.count = value; }
}
}
public static class WidgetManager
{
public static void CatastrophicErrorResetWidgetCount( Widget widget )
{
Type type = widget.GetType();
PropertyInfo info = type.GetProperty("Count",BindingFlags.Instance|BindingFlags.NonPublic);
info.SetValue(widget,0,null);
}
}
The reason this is a design flaw is because it seems muddled between the scope of the two objects.
The properties of a class should be accessible in the context of that class, at least internally.
It sounds like the settable property on your item class is really a property of the manager class.
You could do something similar to what you want by closely coupling the two classes:
public class MyItem {
internal MyItemManager manager { get;set; }
public string Property1 {
get { return manager.GetPropertyForItem( this ); }
}
}
Unfortunately this isn't great design either.
What your looking for is what C++ calls a Friend class but neither c# or vb has this functionality. There is a lot of debate as to the merit of such functionality since it almost encourages very strong coupling between classes. The only way you could implement this in c# would be with reflection.
If your goal is to have a class Foo let some property (e.g. Bar, of type Biz) to be changed by some other object, without exposing it publicly, a simple way to do that is to have an instance of Foo which is supposed to be changeable by some other object to pass that other object an Action<Biz> which points to a private method that changes Bar to the passed-in value. The other object may use that delegate to change the Bar value of the object that supplied it.
If one wishes to have give all instances of some type Woozle the ability to set the Bar value of any instance of Foo, rather than exposing such abilities on a per-instance basis, one may require that Woozle have a public static method Woozle.InstallFooBarSetter which takes a parameter of type Action<Foo, Biz> and one of type Object. Foo should then have a static method WoozleRequestBarSetter which takes an Object, and passes it to Woozle.InstallFooBarSetter along with an Action<Foo,Biz>. The class initializer for Woozle should generate a new Object, and pass it to Foo.RequestBarSetter; that will pass the object to Woozle.InstallFooBarSetter along with a delegate. Woozle can then confirm that the passed-in object is the one that it generated, and--if so--install the appropriate delegate. Doing things this way will ensure that nobody but Woozle can get the delegate (since the delegate is only passed to Woozle.InstallFooBarSetter), and Woozle can be sure its delegate comes from Foo (since nobody else would have access to the object that Woozle created, and Woozle.InstallFooBarSetter won't do anything without it).
if it is a design flaw depends on what you want to do. You could use the StackTrace class from System.Diagnostics to get the Type of the class setting your property and then compare to the type you want to allow setting yor property..but maybe there are better ways for performing something like this (e.g. boxing)