readonly-fields as targets from subclass constructors - c#

A readonly field should be used when you have a variable that will be known at object-instatiation which should not be changed afterwards.
However one is not allowed to assign readonly fields from constructors of subclasses.
This doesn't even work if the superclass is abstract.
Does anyone have a good explanation why this either isn't a good idea, or lacks in the C# languange?
abstract class Super
{
protected readonly int Field;
}
class Sub : Super
{
public Sub()
{
this.Field = 5; //Not compileable
}
}
PS: You can of course reach the same result by having assignment of the readonly fields in a protected constructor in the superclass.

The only reason I can see for this is because "it was just designed that way", as per the spec:
Direct assignments to readonly fields can only occur as part of that
declaration or in an instance constructor or static constructor in the
same class.
The point of being read only is that it cannot be changed, if derived classes could modify then this would no longer be true and will violate encapsulation (by modifying the internals of another class).

public class Father
{
protected readonly Int32 field;
protected Father (Int32 field)
{
this.field = field;
}
}
public class Son : Father
{
public Son() : base(5)
{
}
}
You may try something like this instead!

I would model this by an abstract/virtual property in C#.
abstract class Super {
protected abstract int Field { get; }
}
class Sub : Super {
protected override int Field { get { return 5; } }
}
In my opinion that's a better solution than to have a constructor that includes each and every readonly field as parameter. For one because the compiler is able to inline this as well and also because the constructor solution will look like this in the derived class:
class Sub : Super {
public Sub() : base(5) { } // 5 what ?? -> need to check definition of super class constructor
}
Also that may not work if you already have a constructor that takes a single int value.

I suppose the main reason is an additional complexity for all .NET language implementations
also, there is always a simple workaround:
abstract class Super
{
protected readonly int Field;
protected Super(int field)
{
this.Field = field;
}
}
class Sub : Super {
public Sub():base(5)
{
}
}

I would prefer to use the protected constructor in superclass (as mentioned by alexm), reachly with xml comments.
This should eliminate the problem what DonAndre told in his code comment.

Related

Correct use of C# 'new' modifier to make protected property public

Let's say I have an abstract base class:
public abstract class BaseClass
{
private MyObject myObject;
protected MyObject PropA
{
get
{
if(myObject == null) this.myObject = new MyObject();
return this.myObject;
}
}
}
...and that in one of my derived classes, I want to make the protected base class property PropA public. Would it be correct to use the new modifier in this context?
public class DerivedClass : BaseClass
{
public new MyObject PropA
{
get
{
return base.PropA;
}
}
}
Would it be correct use of the new modifier in this context?
Technically - yes, there will no errors or warnings.
As for me, using of new keyword itself as a modifier indicates a design drawback.
I'll give one example.
public class MyList<T> : List<T>
{
public int AddCallsCount;
public new void Add(T t)
{
AddCallsCount++;
base.Add(t);
}
}
[TestClass]
public class Test
{
[TestMethod]
public void TestThatsNotGood()
{
List<object> list = new MyList<object>();
list.Add(1);
list.Add(2);
MyList<object> myList = list as MyList<object>;
Assert.AreEqual(0, myList.AddCallsCount);
}
}
It looks like polymorphism works, but actually does not.
UPDATE:
Ok, there is very simplified explanation. I omit explanation of what polymorphism is.
Polymorphims is realized with implementation of abstract\virtual and overriding methods. As soon as neither virtual nor override modifiers are specified MyList<T>.Add is just another 'common' public method. And with MyList<T> inherited List<T>, MyList<T>.Add 'hides' List<T>.Add because name and parameters of both methods are same.
At lower level: as soon as List<T> type definition of method Add isn't marked with virtual keyword, compiler won't search for overriding methods of actual instance type (MyList<T> in this certain case) for variable of given type (List<T> in this certain case).
Definetely it may lead to logic errors and incorrect usage of class API.
Hence, compiler 'thinks' that probably there is a logical mistake or design drawback and warns programmer. The new keyword is just a way to talk to the compiler
yes, I know that it's not good, but I need it because of my bad design
.
The new keyword works and is correct, if you want to add a member in a derived class that has the same name as a member in the base class; however, it seems that this design defies the purpose of abstract classes. Make PropA public and virtual in the base class or public and abstract:
public abstract class BaseClass
{
// Property not implemented here.
public abstract MyObject PropA { get; }
private MyObject _propB;
// Property implemented, but implementation can be overridden in derived class.
public virtual MyObject PropB
{
get { return _propB ?? (_propB = new MyObject()); }
}
public int PropC { get { return 5; } }
}
public class DerivedClass : BaseClass
{
// You must provide an implementation here.
private MyObject _propA;
public override MyObject PropA
{
get { return _propA ?? (_propA = new MyObject()); }
}
// You are free to override this property and to provide an new implementation
// or to do nothing here and to keep the original implementation.
public override MyObject PropB
{
get { return <new implementation...>; }
}
// PropC is inherited as is and is publicly visible through DerivedClass as well.
}
That's correct. Anytime you have a class with a member that has the same name as a member in an inherited class you need to use the new keyword (even if the two properties/methods have different return types).
I would recommend you perhaps
public new string test {
get { return (this as T).test; }
set { (this as T).test = value; }
}
because base give you only parent but if you want to go higher you have to cast.

Preventing Inheritance?

How can i prevent a class from from being inherited
without using Sealed Keyword?
Thanks in advance.
In your class's constructor:
public MyUnsealedClass()
{
if (this.GetType() != typeof(MyUnsealedClass))
throw new Exception("Don't do that");
}
Why not use the sealed keyword though?
Another way is you can make a static method that returns an object of your type and then make the constructor private. This has the advantage that it will create a compile time error instead of a run time error.
You can use private constructors
class Base
{
private Base() {}
}
class Derived : Base
{
// derp
}
Then provide a utility to creaet Base objects (like static methods on Base that have access to the private ctor
class Base
{
private Base() {}
public static Base CreateBase() { return new Base(); }
}
Also, if you want to be able to derive from this class, but you don't want other people doing that, you can make your class internal (or even the ctor internal)
class Base
{
internal Base() { }
}
class Derived : Base
{
}
// in another assembly
class MyOwnDerived : Base
{
// derp
}
You can achieve this by using private constructor, something along the lines:
public class NonInheritableClass
{
static NonInheritableClass GetObject()
{
return new NonInheritableClass();
}
private NonInheritableClass()
{
}
}
Throwing an exception in the constructor will work.
I agree though - why not use sealed? It's there for that reason.
Unless you' are trying to do something else, and if that's the case, there is probably a better solution too.

C# Inheritance to hide inherited Members

I read other threads like this but they didn't work for me.
I got two classes:
public class ClassA
{
public string _shouldBeInteger;
public string _shouldBeBool;
public string _shouldBeDateTime;
}
public class ClassB : ClassA
{
public int? shouldBeInteger
{
get { return (_shouldBeInteger != null) ? Convert.ToInt32(Convert.ToDouble(_shouldBeInteger)) : new int?(); }
set { _shouldBeInteger = Convert.ToString(value); }
}
//... same thing with datetime etc.
}
If I now create a new object of ClassB I get
_shouldBeInteger, _shouldBeBool, _shouldBeDateTime;
shouldBeInteger,shouldBeBool,shouldBeDateTime
But I want to hide the _variables to the User.
Setting them private in ClassB will override them, but I need to access them in order to parse there string values.
Update
There is a ClassC filling ClassAs' values, which mainly is the reason why they have to be writeable. There is no way for me to change the way that works, but I'm fully in Control of ClassA and ClassB
ClassC //not changeAble for me
{
//infomagic filling values of ClassA
}
Setting ClassA variables to private won't work, because programmer of ClassA produced it in a strange way.
Solution
Because ClassA needs to be writeable, but not readable to other classes than inheritated, I finally got this:
ClassA
{
public string _shouldBeInteger { protected get; set; }
//and so on
}
which causes ClassB to work with theese properties, without giving them outside.
Intellisense still shows them, but you might consider using:
[EditorBrowsable(EditorBrowsableState.Never)]
to solve that.
Thanks to all.
I think you can solve your problem using:
public class ClassA
{
protected string _shouldBeInteger;
protected string _shouldBeBool;
protected string _shouldBeDateTime;
}
so those variables are accessible to derived classes but not to user.
EDITED after user update:
I don't know if this could be a vali solution for you, but try:
public class ClassB : ClassA
{
public new int? _shouldBeInteger
{
get { return (base._shouldBeInteger != null) ?
Convert.ToInt32(Convert.ToDouble(base._shouldBeInteger)) :
new int?(); }
set { base._shouldBeInteger = Convert.ToString(value); }
}
}
Inheritance can't hide the members as you would think. The new modifier exists to "hide" a base member, but that doesn't play nice when talking to base types.
http://msdn.microsoft.com/en-us/library/435f1dw2.aspx
You can either change the access level of the fields (the preferred way) or you can wrap the class instead of inheriting from it and provide simple pass-through methods to delegate to the wrapped class. This is called the Adapter Pattern:
public class ClassB
{
private ClassA _wrappedClass;
}
Just as an aside, your public fields are following the naming convention commonly used for private fields.
The required access level for derived classes is protected. If the members are used publicly but in the same assembly you can use protected internal. If the members are used publicly by other assemblies... I'd suggest refactoring.
The problem is that you declared the fields public in the base class. In order not to violate the polymorphic nature of inheritance, anything public in the base class must be public in all derived classes as well. If you could change that, you could never be sure that a ClassB could be passed to something expecting a ClassA.
Therefore, as other people have suggested, you probably want the base class fields to be declared protected, which is like private except derived classes can see them.
However if you do need to access them via an actual instance of ClassA, you could declare them private and give them virtual public properties which the derived class can then override. This at least allows the derived class to change their behaviour, but it still can't actually hide them.
If that also doesn't fit, then it's probably worth considering using composition instead of inheritance because the substitution principle is actually getting in your way, and that's an inheritance fundamental.
If you don't have control over ClassA, you'll need to create a wrapper/adapter class like so:
public class ClassB
{
private readonly _classA = new ClassA();
public int? shouldBeInteger
{
get
{
return (this._classA._shouldBeInteger != null)
? Convert.ToInt32(Convert.ToDouble(this._classA._shouldBeInteger))
: new int?();
}
set
{
this._classA._shouldBeInteger = Convert.ToString(value);
}
}
}
public class ClassB
{
private int shouldBeInteger;
public int ShouldBeInteger
{
get { return shouldBeInteger; }
set { shouldBeInteger = value; }
}
}
OR
public class ClassB
{
public int ShouldBeInteger{ get; set; }
}
In both of this case ShouldBeInteger will be accesible outside the class.
In first case there were a private field, which cannot be accesible outside the class,
values to private filed can be set through the public field.
In second case the compiler automatically create a private backing field and do the same
process as above. This is auto implemented property.
Hope this may help you.

How do I create a method or property in C# that is public, yet not inheritable?

Here is an example. I have two classes, one inherited, and both have a function with the same name, but different arguments:
public class MyClass
{
//public class members
public MyClass()
{
//constructor code
}
public void Copy(MyClass classToCopy)
{
//copy code
}
}
public class InheritedClass : MyClass
{
//public class members
public InheritedClass():base()
{
//constructor code
}
public void Copy(InheritedClass inheritedClassToCopy)
{
//copy code
}
}
My question is how do I make the base class' copy method (MyClass.Copy) non-inheritable or non-visible in InheritedClass? I don't want to be able to do this:
MyClass a;
InheritedClass b;
b.Copy(a);
Does this make sense, or should I keep this functionality in there? Can what I'm asking even be done?
Does this make sense, or should I keep this functionality in there? Can what I'm asking even be done?
Trying to hide a public method like this when used by a base class is problematic. You're purposely trying to violate the Liskov substitution principle.
You can't do what you are wanting to do here; C# does not allow negative variance in inherited members. (almost no languages truly do, actually)
It may be that you don't want an inherited class here at all, though; what you may really want is an interface. Or... your two classes here may not have the correct relationship; perhaps they should both instead be common siblings of a third class, which is their parent.
You can use explicit interface implementation to hide this method from the inheritor. But you will need to add an interface of course and you will need to cast your type to the interface to call your method:
public interface MyInterface
{
void Copy(MyClass classToCopy)
}
public class MyClass : MyInterface
{
void MyInterface.Copy(MyClass classToCopy)
{
//copy code
}
}
This is not possible. An inherited class inherits all public and protected members, methods and properties. Using the sealed modifier with make it non-overridable, but still accessible to your inherited class.
What everyone else said, but if I am inferring your goal correctly, it is to make sure that InheritedClass users never use the MyClass method. In that case, exclude it from MyClass and make two classes that inherit it.
Make MyBaseClass abstract if it should not be instantiated (most likely).
(Edited -- you probably would want to include copy code for anything that's part of the base class in the base class)
public abstract class MyBaseClass
{
public MyClass()
{
//constructor code
}
protected void Copy(MyBaseClass classToCopy)
{
//copy code
}
// other methods that all inherited classes can use
}
public class MyClass: MyBaseClass
{
public MyClass():base()
{
//constructor code
}
public void Copy(MyClass myClassToCopy)
{
base.Copy(myClassToCopy);
//specific copy code for this extensions in this class
}
}
public class InheritedClass : MyBaseClass
{
public InheritedClass():base()
{
//constructor code
}
public void Copy(InheritedClass inheritedClassToCopy)
{
base.Copy(myClassToCopy);
//specific copy code for this extensions in this class
}
}

Why can't I declare C# methods virtual and static?

I have a helper class that is just a bunch of static methods and would like to subclass the helper class. Some behavior is unique depending on the subclass so I would like to call a virtual method from the base class, but since all the methods are static I can't create a plain virtual method (need object reference in order to access virtual method).
Is there any way around this? I guess I could use a singleton.. HelperClass.Instance.HelperMethod() isn't so much worse than HelperClass.HelperMethod(). Brownie points for anyone that can point out some languages that support virtual static methods.
Edit: OK yeah I'm crazy. Google search results had me thinking I wasn't for a bit there.
I don't think you are crazy. You just want to use what is impossible currently in .NET.
Your request for virtual static method would have so much sense if we are talking about generics.
For example my future request for CLR designers is to allow me to write intereface like this:
public interface ISumable<T>
{
static T Add(T left, T right);
}
and use it like this:
public T Aggregate<T>(T left, T right) where T : ISumable<T>
{
return T.Add(left, right);
}
But it's impossible right now, so I'm doing it like this:
public static class Static<T> where T : new()
{
public static T Value = new T();
}
public interface ISumable<T>
{
T Add(T left, T right);
}
public T Aggregate<T>(T left, T right) where T : ISumable<T>, new()
{
return Static<T>.Value.Add(left, right);
}
Virtual static methods don't make sense. If I call HelperClass.HelperMethod();, why would I expect some random subclass' method to be called? The solution really breaks down when you have 2 subclasses of HelperClass - which one would you use?
If you want to have overrideable static-type methods you should probably go with:
A singleton, if you want the same subclass to be used globally.
A tradition class hierarchy, with a factory or dependency injection, if you want different behavior in different parts of your application.
Choose whichever solution makes more sense in your situation.
You can achieve the same effect by just having a regular static method and then shadow it with the new keyword
public class Base
{
//Other stuff
public static void DoSomething()
{
Console.WriteLine("Base");
}
}
public class SomeClass : Base
{
public new static void DoSomething()
{
Console.WriteLine("SomeClass");
}
}
public class SomeOtherClass : Base
{
}
Then you can call the methods like so
Base.DoSomething(); //Base
SomeClass.DoSomething(); //SomeClass
SomeOtherClass.DoSomething(); //Base
Indeed, this can be done in Delphi. An example:
type
TForm1 = class(TForm)
procedure FormShow(Sender: TObject);
end;
TTestClass = class
public
class procedure TestMethod(); virtual;
end;
TTestDerivedClass = class(TTestClass)
public
class procedure TestMethod(); override;
end;
TTestMetaClass = class of TTestClass;
var
Form1: TForm1;
implementation
{$R *.dfm}
class procedure TTestClass.TestMethod();
begin
Application.MessageBox('base', 'Message');
end;
class procedure TTestDerivedClass.TestMethod();
begin
Application.MessageBox('descendant', 'Message');
end;
procedure TForm1.FormShow(Sender: TObject);
var
sample: TTestMetaClass;
begin
sample := TTestClass;
sample.TestMethod;
sample := TTestDerivedClass;
sample.TestMethod;
end;
Quite interesting. I no longer use Delphi, but I recall being able to very easily create different types of controls on a custom designer canvas using the metaclass feature: the control class, eg. TButton, TTextBox etc. was a parameter, and I could call the appropriate constructor using the actual metaclass argument.
Kind of the poor man's factory pattern :)
I come from Delphi and this is a feature among many that I sorely miss in c#. Delphi would allow you to create typed type references and you could pass the type of a derived class wherever the type of a parent class was needed. This treatment of types as objects had powerful utility. In particular allowing run time determination of meta data. I am horribly mixing syntax here but in c# it would look something like:
class Root {
public static virtual string TestMethod() {return "Root"; }
}
TRootClass = class of TRoot; // Here is the typed type declaration
class Derived : Root {
public static overide string TestMethod(){ return "derived"; }
}
class Test {
public static string Run(){
TRootClass rc;
rc = Root;
Test(rc);
rc = Derived();
Test(rc);
}
public static Test(TRootClass AClass){
string str = AClass.TestMethod();
Console.WriteLine(str);
}
}
would produce:
Root
derived
You are not crazy. What you are referring to is called Late Static Binding; it's been recently added to PHP. There's a great thread that describes it - here: When would you need to use late static binding?
a static method exists outside of an instance of a class. It cannot use any non-static data.
a virtual method will be "overwritten" by an overloaded function depending of the type of an instance.
so you have a clear contradiction between static and virtual.
This is not a problem of support, It is a concept.
Update: I was proven wrong here(see comments):
So I doubt you will find any OOP-Language which will support virtual
static methods.
There is a way to force an inheritance of "abstract static" methods from an abstract generic class. See as follow :
public abstract class Mother<T> where T : Mother<T>, new()
{
public abstract void DoSomething();
public static void Do()
{
(new T()).DoSomething();
}
}
public class ChildA : Mother<ChildA>
{
public override void DoSomething() { /* Your Code */ }
}
public class ChildB : Mother<ChildB>
{
public override void DoSomething() { /* Your Code */ }
}
Example (using the previous Mother):
public class ChildA : Mother<ChildA>
{
public override void DoSomething() { Console.WriteLine("42"); }
}
public class ChildB : Mother<ChildB>
{
public override void DoSomething() { Console.WriteLine("12"); }
}
public class Program
{
static void Main()
{
ChildA.Do(); //42
ChildB.Do(); //12
Console.ReadKey();
}
}
It's not that great since you can inherit from only one abstract class and it will ask you to be lenient with your new() implementation.
More, I think it will be costly memory-wise depending on the size of your inherited classes.
In case you have memory issue, you would have to set every properties/variables after your new in a public method which is an awful way to have default values.
I heard that Delphi suports something like this. It seems it does it by making classes object instances of a metaclass.
I've not seen it work, so I'm not sure that it works, or what's the point for that.
P.S. Please correct me if I'm wrong, since it's not my domain.
Because a virtual method uses the defined type of the instantiated object to determine which implementation to execute, (as opposed to the declared type of the reference variable)
... and static, of course, is all about not caring if there's even an instantiated instance of the class at all...
So these are incompatible.
Bottom line, is if you want to change behavior based on which subclass an instance is, then the methods should have been virtual methods on the base class, not static methods.
But, as you already have these static methods, and now need to override them, you can solve your problem by this:
Add virtual instance methods to the base class that simply delegate to the static methods, and then override those virtual instance wrapper methods (not the static ones) in each derived subclass, as appropriate...
It is actually possible to combine virtual and static for a method or a member by using the keyword new instead of virtual.
Here is an example:
class Car
{
public static int TyreCount = 4;
public virtual int GetTyreCount() { return TyreCount; }
}
class Tricar : Car
{
public static new int TyreCount = 3;
public override int GetTyreCount() { return TyreCount; }
}
...
Car[] cc = new Car[] { new Tricar(), new Car() };
int t0 = cc[0].GetTyreCount(); // t0 == 3
int t1 = cc[1].GetTyreCount(); // t1 == 4
Obviously the TyreCount value could have been set in the overridden GetTyreCount method, but this avoids duplicating the value. It is possible to get the value both from the class and the class instance.
Now can someone find a really intelligent usage of that feature?
Mart got it right with the 'new' keyword.
I actually got here because I needed this type of functionality and Mart's solution works fine. In fact I took it one better and made my base class method abstract to force the programmer to supply this field.
My scenario was as follows:
I have a base class HouseDeed. Each House type is derived from HouseDeed must have a price.
Here is the partial base HouseDeed class:
public abstract class HouseDeed : Item
{
public static int m_price = 0;
public abstract int Price { get; }
/* more impl here */
}
Now lets look at two derived house types:
public class FieldStoneHouseDeed : HouseDeed
{
public static new int m_price = 43800;
public override int Price { get { return m_price; } }
/* more impl here */
}
and...
public class SmallTowerDeed : HouseDeed
{
public static new int m_price = 88500;
public override int Price { get { return m_price; } }
/* more impl here */
}
As you can see I can access the price of the house via type SmallTowerDeed.m_price, and the instance new SmallTowerDeed().Price
And being abstract, this mechanism nags the programmer into supplying a price for each new derived house type.
Someone pointed how 'static virtual' and 'virtual' are conceptually at odds with one another. I disagree. In this example, the static methods do not need access to the instance data, and so the requirements that (1) the price be available via the TYPE alone, and that (2) a price be supplied are met.
An override method provides a new implementation of a member that is inherited from a base class. The method that is overridden by an override declaration is known as the overridden base method. The overridden base method must have the same signature as the override method.
You cannot override a non-virtual or static method. The overridden base method must be virtual, abstract, or override.
An override declaration cannot change the accessibility of the virtual method. Both the override method and the virtual method must have the same access level modifier.
You cannot use the new, static, or virtual modifiers to modify an override method.
An overriding property declaration must specify exactly the same access modifier, type, and name as the inherited property, and the overridden property must be virtual, abstract, or override.
You can use the new keyword
namespace AspDotNetStorefront
{
// This Class is need to override StudioOnlineCommonHelper Methods in a branch
public class StudioOnlineCommonHelper : StudioOnlineCore.StudioOnlineCommonHelper
{
//
public static new void DoBusinessRulesChecks(Page page)
{
StudioOnlineCore.StudioOnlineCommonHelper.DoBusinessRulesChecks(page);
}
}
}
It is possible to simulate the functionality by using the new keyword in the derived class and throwing the NotSupportedException() in the base.
public class BaseClass{
public static string GetString(){
throw new NotSupportedException(); // This is not possible
}
}
public class DerivedClassA : BaseClass {
public static new string GetString(){
return "This is derived class A";
}
}
public class DerivedClassB : BaseClass {
public static new string GetString(){
return "This is derived class B";
}
}
static public void Main(String[] args)
{
Console.WriteLine(DerivedClassA.GetString()); // Prints "This is derived class A"
Console.WriteLine(DerivedClassB.GetString()); // Prints "This is derived class B"
Console.WriteLine(BaseClass.GetString()); // Throws NotSupportedException
}
Due to the fact that it is not possible to detect this condition at compile time and that IntelliSense won't suggest that such function should be implemented in the derived class, this is a potential headache.
One comment also suggested to use NotImplemetedException(). Microsoft's documentation indicates that neither of these exceptions should be handled so any of them should work.
The differences between NotSupportedException and NotImplemetedException are commented in this blog.
You will be able to soon, in C# 11!
From Tutorial: Explore C# 11 feature - static virtual members in interfaces:
C# 11 and .NET 7 include static virtual members in interfaces. This feature enables you to define interfaces that include overloaded operators or other static members.

Categories

Resources