I wanted to elaborate on the current project i'm working on but that would be kind long. Instead I'll just post a programming riddle which basically explains what i'm trying to accomplish. :)
abstract class A
{
// key = Derived Class name, value = list of properties the derive class exposes.
private static Dictionary<string, List<string>> _DerivedPropertyNames;
static A()
{
InitializeDerivedPropertyNames();
}
private static void InitializeDerivedPropertyNames()
{
//...???...
}
}
The riddle is how can you create an abstract base class which will hold a static cache of all its derived classes properties?
Note that the idea is to avoid loading an assembly by name.
There is no easy (efficient) way to do this in the base class.
Simply implement a static constructor in every derived class and use it to register the properties.
Also take a look at Dependency properties in the WPF Fx, for comparison.
If you can wait for instances of the child types to be instantiated, then you could use A's regular constructor to register the implementing class:
public A()
{
Type childType = GetType();
string className = childType.Name;
if (!_DerivedPropertyNames.ContainsKey(className)) {
// add properties for this class
}
}
It will be very difficult for you to get the job done in the static constructor, before any instantiation, without adding logic in the child classes (which I suppose you don't want). The reason is that you won't be able to enforce all assemblies containing types that implement A to be loaded when A's static constructor is called.
Related
I know that in C# we cant override non virtual fields and methods but I have the following case:
Class Base
{
public static int a {get;set;}
public static void b()
{
// it uses a
}
public static void c()
{
// it uses a
}
public static string d {get {return a.ToString();}}
}
Class MyClass :Base
{
//...
}
now in my class MyClass i want to override the property a that all of Base class methods and properties start using the the overwritten property that i implemented, taking into considerations that i don't have access to change Base class
Is there any way to do this even if i had to re-implement the getter method of that property?
This is a static property, so it's used in the form Base.a. Whatever you do, the calling code will still resolve to the Base class, and then to it's static property a.
E.g
//old calling code
Base.a = 7; // does not create an instance
Console.WriteLine(Base.a);
class MyClass :Base
{
public static string a {get; set;}
}
//new calling code
MyClass.a = "some string"; // uses whatever a you defined in MyClass
Console.WriteLine(MyClass.a);
The best way is perhaps to introduce a new property by a different name, or have your class wrap the base class instead of extending it. Together with extension methods, these are the most common ways to build upon functionality of a class you don't have access to.
You can also re-introduce the property using the new keyword, but I would not recommend that. It hides the base class methods, which is dangerous because users of your code may end up calling the wrong thing. Whether new is warranted in this case very much depends on your exact use case.
Finally note, as Daniel remarked in the comments to your original post, that the methods in your base class seem to be static. So even if you had base class access, you would not be able to make them virtual. Actually having loads of static methods is generally bad design, except special cases such as object factories or extension method containers.
I have need to use one of two custom file readers classes; one to read a fixed width file and one for a CSV file. Each of these readers will have certain properties, etc. I want to use factory methods and have private constructors so I can run some business logic before creating the objects.
EDIT: better examples
//simple class with it's own factory method
class Class1
{
private Class1()
{
//constructor code
}
public static Class1 CreateClass()
{
//do some business logic here
return new Class1();
}
}
What I want to be able to do is define a base class, then override the factory. I guess the problem is that a static class belongs to the base CLASS, so can never be overriden, even though they ARE inherited. This code works
public class BaseClass
{
//some common properties / fields here
public string SomeField;
//some common methods here
//empty constructor
protected BaseClass() { }
//cannot have a virtual static class!
//Would really like to make this a virtual method
public static BaseClass CreateClass()
{
throw new NotImplementedException("BaseClass is meant to be derived");
}
public static string DoCommonStaticThing(){
return "I don't know why you'd ever do this";
}
}
public class DerivedClass1 : BaseClass
{
//private constructor
private DerivedClass1() {}
//concrete factory method
//would really like to say "override" here
public static BaseClass CreateClass()
{
DerivedClass1 d1 = new DerivedClass1();
d1.SomeField = "I'm a derived class\r\n" + DoCommonStaticThing();
return d1;
}
}
EDIT: To clarify further, what I'm trying to do is put some common functionality in my base class, but define an interface for my file-format-specific methods. Some of the methods are common, but the business logic for the constructor(s) is file format specific. My code above works, but it seems to me it would be better to mark the base class factory method as virtual, and the derived class factory method as "override".
I tried to do this, but got "A static member cannot be marked as override, virtual, or abstract".
What's the right way to achieve my goals?
First, explaining your specific error message: you cannot inherit static members because they belong to the type being defined, not the instance of the type. Inheritance modifiers such as override, virtual, and abstract do not apply to static members.
Second:
Typically when you follow a factory pattern, you have a factory class whose job is to instantiate concrete classes and return those instances cast as a base class or interface. Details vary as to how the factory chooses which concrete class to instantiate, and I won't get into that, but at the fundamental level, that's what a factory does.
So in order to create a factory pattern using the example you provided, you'll need at least four types, which, following your example, could probably be named ReaderBase, ReaderFactory, CsvReader, and FixedWidthReader. Rather than ReaderBase, you might consider IReader -- the choice depends on whether your abstract class pre-implements any functionality that is shared across all Readers.
CsvReader and FixedWidthReader inherit from either IReader or ReaderBase, and ReaderFactory has at least one method called, for example, InstantiateReader, which returns an IReader or ReaderBase. InstantiateReader does the work of determining whether to instantiate a CsvReader or a FixedWidthReader, based on some external criteria.
In C#, a superclass's static members are "inherited" into the subclasses scope. For instance:
class A { public static int M() { return 1; } }
class B : A {}
class C : A { public new static int M() { return 2; } }
[...]
A.M(); //returns 1
B.M(); //returns 1 - this is equivalent to A.M()
C.M(); //returns 2 - this is not equivalent to A.M()
Now, you can't inherit static classes, and the only place I can imagine that static inheritance might matter ignores it entirely: although you can make a generic constraint that requires a type parameter T to be a subclass of A, you still cannot call T.M() (which probably simplifies things for the VM), let alone write a different M implementation in a subclass and use that.
So, the "inheritance" of static members merely looks like namespace pollution; even if you explicitly qualify the name (i.e. B.M) A's version is still resolved.
Edit compare with namespaces:
namespace N1{ class X(); }
namespace N1.N2 { class X(); }
namespace N1.N2.N3 { [...] }
Within N1.N2.N3 It makes sense that if I use X without qualification it refers to N1.N2.X. But if I explicitly refer to N1.N2.N3.X - and no such class exists - I don't expect it to find N2's version; and indeed to compiler reports an error if you try this. By contrast, if I explicitly refer to B.M(), why doesn't the compiler report an error? After all, there's no "M" method in "B"...
What purpose does this inheritance have? Can this feature be used constructively somehow?
So, the "inheritance" of static
members merely looks like namespace
pollution
That's right, except that one guy's pollution is another guy's added spicy flavouring.
I think Martin Fowler, in his work on DSLs, has suggested using inheritance in this way to allow convenient access to static methods, allowing those methods to be used without class name qualification. So the calling code has to be in a class that inherits the class in which the methods are defined. (I think it's a rotten idea.)
In my opinion, static members should not be mixed into a class with a non-static purpose, and the issue you raise here is part of the reason why it's important not to mix them.
Hiding private static mutable data inside the implementation of an otherwise "instancey" class is particularly horrible. But then there are static methods, which are even worse mixers. Here's a typical use of static methods mixed into a class:
public class Thing
{
// typical per-instance stuff
int _member1;
protected virtual void Foo() { ... }
public void Bar() { ... }
// factory method
public static Thing Make()
{
return new Thing();
}
}
It's the static factory method pattern. It's pointless most of the time, but even worse is that now we have this:
public class AnotherThing : Thing { }
This now has a static Make method which returns a Thing, not a AnotherThing.
This kind of mismatch strongly implies that anything with static methods should be sealed. Static members fail to integrate well with inheritance. It makes no sense to have them heritable. So I keep static things in separate static classes, and I gripe about redundantly having to declare every member static when I've already said that the class is static.
But it's just one of those too-late-now things. All real, working languages (and libraries, and products) have a few of them. C# has remarkably few.
I rather have access to all my based static members in derived classes.
Otherwise i would need to know exactly where the static member was defined and call it explicitly.
When using Intellisense you can automatically know every static member available to that kind of class.
Of course, they are not inherited, it's just a shortcut
That's how it works, would probably just be a stupid answer in most cases. But in this case, it is how it works; since you derive from A you say that you are A + the extra features you add.
Therefore you need to be able to access the same variables that you would through an instance of A.
However, inheriting a static class makes no sense while access to the static members / fields / methods does.
An example of this is the following:
internal class BaseUser
{
public static string DefaultUserPool { get; set; }
}
internal class User : BaseUser
{
public int Id { get; set; }
public string Name { get; set; }
public User Parent { get; set; }
}
Where the test looks like this:
User.DefaultUserPool = "Test";
BaseUser.DefaultUserPool = "Second Test";
Console.WriteLine(User.DefaultUserPool);
Console.WriteLine(BaseUser.DefaultUserPool);
Both of the WriteLines outputs "Second Test", this is because both BaseUser and User should use DefaultUserPool, by design. And overriding static implemented methods wouldn't make mucn sense since it's just an accessor in the child-class.
There can be only one. Overriding it would mean that there's a new implementation for that sub-class, which would kill the term "static".
Actually, as I understand it, this is just a shortcut provided by the compiler. Syntax sugar. B.M() will just compile to A.M() since B does not have a static M() and A does. It's for easier writing, nothing else. There is no "static inheritance".
Added: And the requirement for new when "redefining" is just so that you don't accidentally shoot yourself in the foot.
I think it's for accessing protected static members of the base class.
class Base
{
protected static void Helper(string s)
{
Console.WriteLine(s);
}
}
class Subclass : Base
{
public void Run()
{
Helper("From the subclass");
}
}
So... What's the alternative?
The question mentions...
why doesn't the compiler report an error? After all, there's no "M" method in "B"...
But there is a derived "M" method in "B" class.
If the compiler did not present the programmer a unified virtual table for base cases, then the programmer would have to go hunting through base types to find static methods. This would break polymorphism.
Wikipedia...
Subtype polymorphism, almost universally called just polymorphism in the context of object-oriented programming, is the ability of one type, A, to appear as and be used like another type, B....
In strongly typed languages, polymorphism usually means that type A somehow derives from type B, or type C implements an interface that represents type B.
I always see it a means of preventing any form of polymorphism by the inheriting class on those items that you wish to retain the same function for all child classes.
ignore the above for some reason I was thinking of sealed instead of static
I suppose that you'd use static member variables and functions in order to ensure that any data or functionallity is not dependent on the a class instance as it would be instantiated only the once.
An example of use would be say a counter value that would keep a live count of all instances of a superclass's subclasses (each subclass increments the static count value on construction). This count value would be available and equal for all instances of the subclass.
I recently ran into a problem where it seems I need a 'static abstract' method. I know why it is impossible, but how can I work around this limitation?
For example I have an abstract class which has a description string. Since this string is common for all instances, it is marked as static, but I want to require that all classes derived from this class provide their own Description property so I marked it as abstract:
abstract class AbstractBase
{
...
public static abstract string Description{get;}
...
}
It won't compile of course. I thought of using interfaces but interfaces may not contain static method signatures.
Should I make it simply non-static, and always get an instance to get that class specific information?
Any ideas?
You can't.
The place to do this is with Attributes.
Eg
[Name("FooClass")]
class Foo
{
}
If you don't mind deferring to implementations to sensibly implement the Description property, you can simply do
public abstract string ClassDescription {get; }
// ClassDescription is more intention-revealing than Description
And implementing classes would do something like this:
static string classDescription="My Description for this class";
override string ClassDescription { get { return classDescription; } }
Then, your classes are required to follow the contract of having a description, but you leave it to them to do it sensibly. There's no way of specifying an implementation in an object-oriented fashion (except through cruel, fragile hacks).
However, in my mind this Description is class metadata, so I would prefer to use the attribute mechanism as others have described. If you are particularly worried about multiple uses of reflection, create an object which reflects over the attribute that you're concerned with, and store a dictionary between the Type and the Description. That will minimize the reflection (other than run time type inspection, which isn't all that bad). The dictionary can be stored as a member of whatever class that typically needs this information, or, if clients across the domain require it, via a singleton or context object.
If it is static, there is only one instance of the variable, I don't see how inheritance would make sense if we could do what you want to accomplish with static vars in derived classes. Personally I think you are going to far to try to avoid a instance var.
Why not just the classic way?
abstract class AbstractBase
{
protected string _Description = "I am boring abstract default value";
}
class Foo : AbstractBase {
public Foo() {
_Description = "I am foo!";
}
}
Combining static and abstract is somewhat meaningless, yes. The idea behind static is one need not present an instance of the class in order to use the member in question; however with abstract, one expects an instance to be of a derived class that provides a concrete implementation.
I can see why you'd want this sort of combination, but the fact is the only effect would be to deny the implementation use of 'this' or any non-static members. That is, the parent class would dictate a restriction in the implementation of the derived class, even though there's no underlying difference between calling an abstract or 'static abstract' member (as both would need a concrete instance to figure out what implementation to use)
A possible workaround is to define a Singleton of your derived class in your base class with the help of Generics.
import System;
public abstract class AbstractBase<T>
where T : AbstractBase<T>, new()
{
private static T _instance = new T();
public abstract string Description { get; }
public static string GetDescription()
{
return _instance.Description;
}
}
public class DerivedClass : AbstractBase<DerivedClass>
{
public override string Description => "This is the derived Class";
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(DerivedClass.GetDescription());
Console.ReadKey();
}
}
The trick is to tell your AbstractBase<T> some details about how DerivedClass is implemented:
It is newable with where T: new() so it can create a Singleton instance
It derives from itself with where T : AbstractBase<T> so it knows that there will be a implementation of Description
This way _instance contains the Description field which can be called in the static Method GetDescription().
This forces you to overwrite Descriptionin your DerivedClass and allows you to call its value with DerivedClass.GetDescription()
It's not static if it has to be called on an instance.
If you're not calling it on an instance, then there's no polymorphism at play (i.e. ChildA.Description is completely unrelated to ChildB.Description as far as the language is concerned).
You can...
In the abstract class...
protected abstract InWindow WindowInstance { get; set; }
In the derived class...
private static InWindow _instance;
protected override InWindow WindowInstance
{
get => _instance;
set => _instance = value;
}
You could make the "abstract" base method throw an Exception, so then a developer is "warned" if he tries to invoke this method on a child class without overriding.
The downside is that one might extend the class and not use this method. Then refer to other answers provided.
Okay, this is the case:
I got a generic base-class which I need to initialize with some static values. These values have nothing to do with the kind of types my generic baseclass is loaded with.
I want to be able to do something like this:
GenericBaseclass.Initialize(AssociatedObject);
while also having a class doing like this:
public class DerivedClass : GenericBaseclass<int>
{
...
}
Is there any way to accomplish this? I could make a non-generic baseclass and put the static method there, but I don't like that "hack" :)
If the values have nothing to do with the type of the generic base class, then they shouldn't be in the generic base class. They should either be in a completely separate class, or in a non-generic base class of the generic class.
Bear in mind that for static variables, you get a different static variable per type argument combination:
using System;
public class GenericType<TFirst, TSecond>
{
// Never use a public mutable field normally, of course.
public static string Foo;
}
public class Test
{
static void Main()
{
// Assign to different combination
GenericType<string,int>.Foo = "string,int";
GenericType<int,Guid>.Foo = "int,Guid";
GenericType<int,int>.Foo = "int,int";
GenericType<string,string>.Foo = "string,string";
// Verify that they really are different variables
Console.WriteLine(GenericType<string,int>.Foo);
Console.WriteLine(GenericType<int,Guid>.Foo);
Console.WriteLine(GenericType<int,int>.Foo);
Console.WriteLine(GenericType<string,string>.Foo);
}
}
It sounds like you don't really want a different static variable per T of your generic base class - so you can't have it in your generic base class.
That's exactly what you have to do. When you have a type parameter, each different instantiation of the type is a separate type. This leads to separate static variables.
The only workaround is to have a base class that the generic class derives from.