static abstract class - c#

I need a way to create a static class where some constants can be case specific, but hard-coded.
What I really want to do is have a class where several constants are provided when the class is extended - I want the 'constants' hard-coded. I figured I will make the some abstract properties and define the get { return constant; } when extending the class.
I know that is not possible, so now I am facing two options and am wondering what would be best and why (if there are options I'm missing please let me know!)
Create a static class with nullable fields and throw an exception if the fields are null when the static method is called.
Give up the static class. Have a non-static class with abstract properties and create an instance of the object wherever I need it even though all the functionality really is static.
I know this might be subjective and case-dependant, however I am going around in circles when thinking about this and could really do with some external input. That plus I hope there might be away of doing what I want and I'm just thinking about this wrong.
Update: Code: I will try to write some code that describes what I'd like to accomplish. I know this code can't work!
Imagine that the abstract class Calculation is in a dll, used by many projects. The functionality is the same for all of them, just the Constant varies from project to project.
public abstract static class Calculation
{
private abstract int Constant { get; } //The constant is unknown at this time
public static int Calculate(int inputValue)
{
return inputValue * Constant;
}
}
The class Calc is defined in a separate project where the functionality is needed and the Constant is known.
public static class Calc : Calculation
{
private override int Constant { get { return 2; }
}
...
static class Program
{
[STAThread]
static void Main()
{
//At some point:
int result = Calc.Calculate(6);
}
}
I suppose the simplest way would be to create a non-static class and create an instance, however I fear having several instances of the class could be expensive and would like to prevent that if possible.
I can't see how I could write this as a singleton pattern without writing it again in each project - having only the Nested class in the dll. That doesn't prevent the implementor to just create an ordinary class and is likely to restart the debate for every project where the code is used.
Update #2 : What I ment with option one is this:
Class in a dll:
public static class Calculation
{
public int? Constant {get; set;}
public static int Calculate(int inputValue)
{
if (Constant == null)
throw new ArgumentNullException();
return inputValue * (int)Constant;
}
}
Usage of the function in a seperate project:
static class Program
{
[STAThread]
static void Main()
{
//At some point:
Calculation.Constant = 2;
int result = Calc.Calculate(6);
}
}
Option one is very simple and elegant, what bothers me about it that nothing forces the implementor to set the Constant. I fear an (admittedly unlikely) scenario where an obscure corner case will cause the property to not be set and for the code to fail (and Constant beeing the last suspect)...

You could make non-static classes that follow singleton, ensuring only one instance of the object ever to exist. I guess that could be the next best thing.

You can't want static and inheritance at the same time ! It simply does not make sense !
If you need to override behavior, you need inheritance !
If you want simplicity of call (one of the advantage of statics), you can use Factory (or singleton if only one instance is needed)
My guess is that you probably have to rethink your model. This set of constants of yours probably represent something that you could extract in a separate class then pass this class to your static method. Would that fit your needs ?

Edit
To your code sample:
public abstract static class Calculation
{
public static int Constant { get; set; }
public static int Calculate(int i) { return i * Constant; }
}
// ...
Calculation.Constant = 6;
Calculation.Calculate(123);
Somewhat more general:
public abstract static class Calculation
{
public struct Context
{
public int Constant, SignificantDigits;
public bool Radians;
}
public static int Calculate(int i, Context ctx) { return i * ctx.Constant; }
}
// ...
Calculation.Calculate(123, new Calculate.Context { Constant = 6 });
First idea:
The closest I can think of is generics:
public interface ISpecifics
{
void DoSomething();
string SomeProp { get; }
}
public static class Static<S>
where S : ISpecifics, new()
{
public static string ExerciseSpecific()
{
var spec = new S();
spec.DoSomething();
return spec.SomeProp;
}
}
Or if you really need a single static type
public static class Static
{
public static string ExerciseSpecific<S>()
where S : ISpecifics, new()
{
var spec = new S();
spec.DoSomething();
return spec.SomeProp;
}
}
Does that help?

I needed pretty much the same thing, so first I made a non-static class with all the functionality.
Then, a static class which instantiates one such non-static class in its static constructor.
Then any of the static methods calls the respective instance methods.
Something like this:
public class CalculationInstance
{
private int constant;
public int Calculate(int inputValue)
{
return inputValue * constant;
}
public void AnyOtherMethod()
{
....
}
public CalculationInstance(int constant)
{
this.constant=constant;
}
}
public static class Calculation
{
const int CONSTANT=2;
private CalculationInstance calc;
static Calculation()
{
calc=new CalculationInstance(CONSTANT);
}
public static int Calculate(int inputValue)
{
return calc.Calculate(inputValue);
}
public static void AnyOtherMethod()
{
calc.AnyOtherMethod();
}
}
static class Program
{
[STAThread]
static void Main()
{
//At some point:
int result = Calculation.Calculate(6);
}
}

I feel this doesn't make sense here, a static class is by default sealed class which means it is sealed for inheritance. So please don't consider having static with abstract.
You can have an abstract class and the child class can inherit and override the methods.

Related

C# static interface or abstract implementation

I have a program that needs to be able to interface with multiple platforms ie read/write files, read/write database or read/write web requests. The platform interface is selected from configuration and does not change while the application is running. I have a single read/write interface class which is inherited by the platform specific classes so that this is abstracted from the rest of the program.
My problem is that I have 10 classes in my framework that will need to use this interface. Instead of making multiple instances of this class, or passing a single reference to every class, I figured it would make sense to make the interface static. Unfortunately I have just learned that Interfaces cannot have static methods, static methods cannot call non-static methods and static methods cannot be abstract.
Can anyone show me another method of approaching this situation?
Edit:
Thanks for everyone's input, here is my solution based on the example given by Patrick Hofman (thank you!)
interface TheInterface
{
void read();
void write();
}
public class X : TheInterface
{
public void read() { //do something }
public void write() { //do something }
}
public class Y : TheInterface
{
public void read() { //do something }
public void write() { //do something }
}
public class FileAccessor
{
public static TheInterface accessor;
public static TheInterface Accessor
{
get
{
if(accessor) return accessor;
}
}
}
This can be called by any class as:
static void Main(string[] args)
{
switch (Config.interface)
{
case "X":
FileAccessor.accessor = new Lazy<X>();
case "Y":
FileAccessor.accessor = new Lazy<Y>();
default:
throw new Lazy<Exception>("Unknown interface: " + Config.interface);
}
FileAccessor.Accessor.read();
}
Indeed, interfaces, or abstract classes can't be static themselves, but the further implementation can. Also, you can use the singleton pattern to make your life easier, and allow inheritance, etc.
public class X : ISomeInterface
{
private X() { }
public static X instance;
public static X Instance
{
get
{
return instance ?? (instance = new X());
}
}
}
Or, using Lazy<T>:
public class X : ISomeInterface
{
private X() { }
public static Lazy<X> instanceLazy = new Lazy<X>(() => new X());
public static X Instance
{
get
{
return instance.Value;
}
}
}
Disclaimer: I am the author of the library described below.
I don't know if this helps you, but I have written a library (very early version yet) that allows you to define static interfaces, by defining normal interfaces and decorating their methods with an attribute named [Static], for example:
public interface IYourInterface
{
[Static]
void DoTheThing();
}
(Note that you don't explicitly add this interface to your implementations.)
Once you have defined the interface, you can instantiate it from within your code with any valid implementation you choose:
return typeof(YourImplementation).ToStaticContract<IYourInterface>();
If the methods can't be found in YourImplementation, this call fails at runtime with an exception.
If the methods are found and this call is successful, then the client code can polymorphically call your static methods like this:
IYourInterface proxy = GetAnImplementation();
proxy.DoTheThing();
You can make a Static Class which has Variable of your Interface.
public static class StaticClass
{
public static ISomeInterface Interface;
}
Now you can access the Instance from everywhere in your Framwork
static void Main(string[] args)
{
StaticClass.Interface = new SomeClass();
}

C# Pass a Class as a parameter

I have an Interface, that has some methods
interface IFunction
{
public double y(double x);
public double yDerivative(double x);
}
and I've got static classes, that are implementing it.
static class TemplateFunction:IFunction
{
public static double y(double x)
{
return 0;
}
public static double yDerivative(double x)
{
return 0;
}
}
I want to pass this classes as a parameter to another function.
AnotherClass.callSomeFunction(TemplateFunction);
And some other class that catches the request
class AnotherClass
{
IFunction function;
public void callSomeFunction(IFunction function)
{
this.fuction = function;
}
}
Well, it doesn't work... I've tried to use the Type expression, but that seams to break the idea of using an interface. Does anyone have an idea, how to correct the code?
Static classes can't implement interfaces, but you can easily overcome this by making your class non static and a generic method:
class AnotherClass
{
IFunction function;
public void callSomeFunction<T>()
where T: IFunction, new()
{
this.fuction = new T();
}
}
This is much close to the syntax you wanted:
AnotherClass.callSomeFunction<TemplateFunction>();
But I actually think that this way is too complicated and likely to confuse someone, you should follow Servy's approach which is way simpler:
AnotherClass.callSomeFunction(TemplateFunction.Instance);
The conceptual way of getting a static class to implement an interface is to use a singleton, even if that singleton contains no state:
public sealed class TemplateFunction : IFunction
{
private TemplateFunction() { }
private static TemplateFunction instance = new TemplateFunction();
public static TemplateFunction Instance { get { return instance; } }
public double y(double x)
{
return 0;
}
public double yDerivative(double x)
{
return 0;
}
}
Another option is to just not use an interface, and instead have your method accept one or more delegates. It's fine if you only need a single method, if you have two it can sometimes be okay, and sometimes not. If you have more than two, it's usually a problem.
public class AnotherClass
{
public static void callSomeFunction(Func<double, double> y
, Func<double, double> yDerivitive)
{
//store delegates for later use
}
}
AnotherClass.callSomeFunction(TemplateFunction.y, TemplateFunction.yDerivative);
How about you use a generic method to catch the type that you are calling for.
Like this:
public void callSomeFunction<T>()
{
//the type is T
//you can create an instance of T with System.Activator.CreateInstance(T) and T's methods
//alternatively if the classes are static you can call the methods with reflection knowing only their name.
}
And anyway, if the reason you want to do this is because you want to have multiple classes that implement the same methods and you want to write a method that will call a certain implementation of those methods based on type, then other solutions might be in order, like overloading.
Or if indeed this is what you want to do, then keep in mind that passing an interface won't allow you to use the approach i presented you with, because the Activator needs to have access to the Type so that it can create an instance.
You can do as Allon said and change the TemplateFunction to none static and then do this:
var anotherClass = new AnotherClass();
var templateFunction = new TemplateFunction();
anotherClass.callSomeFunction(templateFunction);

Why won't this static variable increment when using generics?

I need a certain class to contain a static member that keeps track of everytime an instance of that class is instantiated, essentially so that each instance of the class has a unique index. It works with a non-generic class but this generic implementation fails whenever the type T differs between instances:
class A<T>
{
private static int counter;
private static int Counter {
get {
Increment();
return counter;
}
}
private static void Increment() {
counter++;
}
public int Index;
public A()
{
this.Index = Counter; // using A<T>.Counter makes no difference
Console.WriteLine(this.Index);
}
}
class Program
{
static void Main(string[] args)
{
var a = new A<string>();
var b = new A<string>();
var c = new A<string>();
var d = new A<int>();
}
}
The output is:
1
2
3
1
As soon as the type T switches to int instead of string, the counter resets.
Does this fail by design, and if so what is the reason or how can I get around it? Or is it a bug? It makes sense to some degree because the type T, being generic, is in the class declaration, but..
Each different T creates a new class for A<T> and hence distinct static counters.
To get around this you can use inheritance like so:
abstract class A
{
protected static int counter;
}
class A<T> : A
{
private static int Counter {
get {
Increment();
return counter;
}
}
private static void Increment() {
counter++;
}
public int Index;
public A()
{
this.Index = Counter;
Console.WriteLine(this.Index);
}
}
Not a bug - this is by design, and is a consequence of how generics work.
A generic type like your A<T> serves as a template - when you use type parameters, the compiler generates an actual class with that type T, and a different one will be created for each different type T.
This explains the results you see - there is a static field for the A<int> and another one for the A<string>.
This is because different types are generated under the hood for classes with different generic type parameters. This difference is only for the value type parameters as kindly noted by Ben in comment.
Check out these MSDN articles:
Generics in the Run Time
Reflection and Generic types
EDIT:
Consider following code:
public abstract class GenericBase<T>
{
public static int Counter { get; set; }
}
public class GenericInt : GenericBase<int>
{
}
public class GenericLong : GenericBase<long>
{
}
public class GenericDecimal : GenericBase<decimal>
{
}
[TestFixture]
public class GenericsTests
{
[Test]
public void StaticContextValueTypeTest()
{
GenericDecimal.Counter = 10;
GenericInt.Counter = 1;
GenericLong.Counter = 100;
// !! At this point value of the Counter property
// in all three types will be different - so does not shared across
// all types
}
}
A generic class is a template from which other classes are created. A List<String> and a List<int> are two completely different classes, despite them both originating from List<T>.
Have your generic classes reference a non-generic class that holds the counter. Do not put the static class inside the generic class. This will cause the static class to be generated for each value of T.
class A<T>
{
private static int Counter {
get {
ACounter.Increment();
return ACounter.counter;
}
}
public int Index;
public A()
{
this.Index = Counter;
Console.WriteLine(this.Index);
}
}
static class ACounter
{
static ACounter() {
counter = 0;
}
public static int counter {get; private set;};
public static void Increment() {
counter++;
}
}
Generics with different type parameters are different types. So A<int> and A<string> are different classes, and so are allocated different statics.
This is by design. An instance of A<int> is not an instance of A<string> they are different classes so there are 2 static variable one for each class.
A<int> is actually a different class than A<string>, hence they have different static counters
This is why Resharper flags static variables in generics because so few programmers seems to understand statics and especially statics in generics

How can I access a static property of type T in a generic class?

I am trying to accomplish the following scenario that the generic TestClassWrapper will be able to access static properties of classes it is made of (they will all derive from TestClass). Something like:
public class TestClass
{
public static int x = 5;
}
public class TestClassWrapper<T> where T : TestClass
{
public int test()
{
return T.x;
}
}
Gives the error:
'T' is a 'type parameter', which is not valid in the given context.
Any suggestions?
You can't, basically, at least not without reflection.
One option is to put a delegate in your constructor so that whoever creates an instance can specify how to get at it:
var wrapper = new TestClassWrapper<TestClass>(() => TestClass.x);
You could do it with reflection if necessary:
public class TestClassWrapper<T> where T : TestClass
{
private static readonly FieldInfo field = typeof(T).GetField("x");
public int test()
{
return (int) field.GetValue(null);
}
}
(Add appropriate binding flags if necessary.)
This isn't great, but at least you only need to look up the field once...
Surely you can just write this:
public int test()
{
return TestClass.x;
}
Even in a nontrivial example, you can't override a static field so will always call it from your known base class.
Why not just return TestClass.x?
Generics do not support anything related to static members, so that won't work. My advice would be: don't make it static. Assuming the field genuinely relates to the specific T, you could also use reflection:
return (int) typeof(T).GetField("x").GetValue(null);
but I don't recommend it.
Another solution is to simply not make it static, and work with the new() constraint on T to instantiate the object. Then you can work with an interface, and the wrapper can get the property out of any class that implements that interface:
public interface XExposer
{
Int32 X { get; }
}
public class TestClass : XExposer
{
public Int32 X { get { return 5;} }
}
public class XExposerWrapper<T> where T : XExposer, new()
{
public Int32 X
{
get { return new T().X; }
}
}
In fact, you can change that to public static Int32 X on the TestClassWrapper and simply get it out as Int32 fetchedX = XExposerWrapper<TestClass>.X;
Though since whatever code calls this will have to give the parameter T those same constraints, the wrapper class is pretty unnecessary at this point, since that calling code itself could also just execute new T().X and not bother with the wrapper.
Still, there are some interesting inheritance models where this kind of structure is useful. For example, an abstract class SuperClass<T> where T : SuperClass<T>, new() can both instantiate and return type T in its static functions, effectively allowing you to make inheritable static functions that adapt to the child classes (which would then need to be defined as class ChildClass : SuperClass<ChildClass>). By defining protected abstract functions / properties on the superclass, you can make functions that apply the same logic on any inherited object, but customized to that subclass according to its implementations of these abstracts. I use this for database classes where the table name and fetch query are implemented by the child class. Since the properties are protected, they are never exposed, either.
For example, on database classes, where the actual fetching logic is put in one central abstract class:
public abstract class DbClass<T> where T : DbClass<T>, new()
{
protected abstract String FetchQuery { get; }
protected abstract void Initialize(DatabaseRecord row);
public static T FetchObject(DatabaseSession dbSession, Int32 key)
{
T obj = new T();
DatabaseRecord record = dbSession.RetrieveRecord(obj.FetchQuery, key);
obj.Initialize(record);
return obj;
}
}
And the implementation:
public class User : DbClass<User>
{
public Int32 Key { get; private set;}
public String FirstName { get; set;}
public String LastName { get; set;}
protected override String FetchQuery
{ get { return "SELECT * FROM USER WHERE KEY = {0}";} }
protected override void Initialize(DatabaseRecord row)
{
this.Key = DbTools.SafeGetInt(row.GetField("KEY"));
this.FirstName = DbTools.SafeGetString(row.GetField("FIRST_NAME"));
this.LastName = DbTools.SafeGetString(row.GetField("LAST_NAME"));
}
}
This can be used as:
User usr = User.FetchObject(dbSession, userKey);
This is a rather simplified example, but as you see, this system allows a static function from the parent class to be called on the child class, to return an object of the child class.
T is a type, not parameter or variable so you cannot pick any value from any members. Here is a sample code.
public class UrlRecordService
{
public virtual void SaveSlug<T>(T entity) where T : ISlugSupport
{
if (entity == null)
throw new ArgumentNullException("entity");
int entityId = entity.Id;
string entityName = typeof(T).Name;
}
}
public interface ISlugSupport
{
int Id { get; set; }
}
cjk and Haris Hasan have the most-correct answers to the question as asked. However in this comment the OP implies that he is after something else not quite possible in C#: a way to define a contract for a static member in a derived class.
There isn't a way to strictly define this, but it is possible to set up a pattern that may be implied by a base class (or interface); e.g.:
public class TestClass
{
private static int x;
public virtual int StaticX => x;
}
or if not intended to be used directly
public abstract class AbstractTestClass
{
public abstract int StaticX {get;}
}
or (my preference in this contrived example)
public interface ITest
{
int StaticX {get;}
}
Elsewhere, this pattern of a StaticXxx member may be (loosely) associated with implementations that should back the member with static fields (as in TestClass above).
What's kind of fun is that this can be (re)exposed as static by the generic wrapper, because generic statics are isolated to each type used.
public class TestClassWrapper<T> where T : ITest, new()
{
private readonly static T testInstance = new T();
public static int test() => testInstance.x;
}
This uses a new() condition, but an associated static, generic factory pattern for creating ITest (or TestClass or AbstractTestClass) instances may also be used.
However this may not be feasible if you can't have long-lived instances of the class.
In this situation you assume that T is a subclass of TestClass. Subclasses of TestClass will not have the static int x.

Can't define static abstract string property

I've run into an interesting problem and am looking for some suggestions on how best to handle this...
I have an abstract class that contains a static method that accepts a static string that I would like to define as an abstract property. Problem is that C# doesn't doesn't support the following (see the ConfigurationSectionName and Current properties):
public abstract class ProviderConfiguration : ConfigurationSection
{
private const string _defaultProviderPropertyName = "defaultProvider";
private const string _providersPropertyName = "providers";
protected static string ConfigurationSectionName { get; }
public static Configuration Current
{
get { return Configuration)ConfigurationManager.GetSection(ConfigurationSectionName); }
}
}
I suppose one way to handle this would be to make ConfigurationSectionName NOT abstract and then create a new definition of ConfigurationSectionName in the derived classes, but that feels pretty hackish. Any suggestions would be most welcome.
Gratias!!!
Static members do not have polymorphism, so they can't be abstract. :(
If that's what you need, consider making a Singleton object, and reading the property off that object.
Just use new to override a static method in a derived class. Nothing that makes new a bad thing to do for virtual methods and properties applies since the type name must be supplied:
public class BaseClass
{
public static int Max { get { return 0; } }
}
public class InteriorClass : BaseClass
{
}
public class DerivedClass : InteriorClass
{
public new static int Max { get { return BaseClass.Max + 1; } }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("BaseClass.Max = {0}", BaseClass.Max);
Console.WriteLine("InteriorClass.Max = {0}", InteriorClass.Max);
Console.WriteLine("DerivedClass.Max = {0}", DerivedClass.Max);
Console.ReadKey();
}
}
Ok, this is not exactly to create an static abstract property, but you can achieve the desired effect.
You can get this by using generics:
public abstract class MyAbstractClass<T>
{
public static string MyAbstractString{ get; set; }
public static string GetMyAbstracString()
{
return "Who are you? " + MyAbstractString;
}
}
public class MyDerivedClass : MyAbstractClass<MyDerivedClass>
{
public static new string MyAbstractString
{
get
{
return MyAbstractClass<MyDerivedClass>.MyAbstractString;
}
set
{
MyAbstractClass<MyDerivedClass>.MyAbstractString = value;
}
}
}
public class MyDerivedClassTwo : MyAbstractClass<MyDerivedClassTwo>
{
public static new string MyAbstractString
{
get
{
return MyAbstractClass<MyDerivedClassTwo>.MyAbstractString;
}
set
{
MyAbstractClass<MyDerivedClassTwo>.MyAbstractString = value;
}
}
}
public class Test
{
public void Test()
{
MyDerivedClass.MyAbstractString = "I am MyDerivedClass";
MyDerivedClassTwo.MyAbstractString = "I am MyDerivedClassTwo";
Debug.Print(MyDerivedClass.GetMyAbstracString());
Debug.Print(MyDerivedClassTwo.GetMyAbstracString());
}
}
So, calling the test class you will get:
"Who are you? I am MyDerivedClass"
"Who are you? I am MyDerivedClassTwo"
So, you have an static method in an abstract class but the abstract value is different for each derived class, nice :D
Ok, so, what's going here? The trick is the generic tag, the compiler is generating a different abstract class for each derived type.
As I said it's not an abstract property, but you get all benefits of abstract static properties, which are programming static functions on your abstract class but using different static parameters per type.
Elsewhere on this page, #Gusman proposes the nice solution distilled here:
abstract class AbstractBase { };
abstract class AbstractBase<T> : AbstractBase
{
public static String AbstractStaticProp { get; set; }
};
class Derived1 : AbstractBase<Derived1>
{
public static new String AbstractStaticProp
{
get => AbstractBase<Derived1>.AbstractStaticProp;
set => AbstractBase<Derived1>.AbstractStaticProp = value;
}
};
class Derived2 : AbstractBase<Derived2>
{
public static new String AbstractStaticProp
{
get => AbstractBase<Derived2>.AbstractStaticProp;
set => AbstractBase<Derived2>.AbstractStaticProp = value;
}
};
Moving the static property from a non-generic to generic class means there is no longer necessarily a single global instance. There will be a unique AbstractStaticProp for each distinct type T, so the idea is that specifying the type of the derived class(es) themselves for T guarantees each of them generates a unique static for themselves. There are a few hazards to note with this, however.
If for some reason it is not acceptable for AbstractBaseClass to be generic, then you've only moved the problem elsewhere (albeit more clearly distilled), because you still have to figure out how to statically call from AbstractBase to AbstractBase<T>.
Mainly, there is nothing to enforce or require that any/every given derived class actually does "implement" the (psudo-) "overridden" static property;
Related to this, since there is no compiler (polymorphic) unification going on here, correct signatures (method name, parameter arity, typing, etc.) for the "overridden" methods aren't enforced either.
Although the generic parameter is intended to be "TSelf" of a derived class, in reality T is unconstrained and essentially arbitrary. This opportunizes two new classes of bug: if base class specification Y : AbstractBase<...> mistakenly references a different AbstractBase‑der­ived class X, the values of the "abstract static property" for X and Y will be incorrectly conflated -- and/or -- any usage call-site AbstractBase<T>.AbstractStaticProp with a mistaken type argument (such as DateTime) will spontaneously--and silently--demand a fresh new "instance" of the static property.
The last bullet point can be somewhat mitigated by adding a constraint on the generic base:
/// v---- constraint added
abstract class AbstractBase<TSelf> where TSelf : AbstractBase<TSelf>
{
public static String AbstractStaticProp { get; set; }
};
This eliminates the possibility of class Derived2 : AbstractBase<DateTime> { /*...*/ }, but not the error class Derived2 : AbstractBase<Derived1> { /*...*/ }. This is due to a recurring conundrum that foils all attempts at constraining a generic type to some exact branch of the type-inheritance hierarchy:
The "TSelf problem"
Generic constraints are always at the mercy of the type arguments that are supplied, which seems to entail that it's impossible to construct a generic constraint that guarantees that some particular TArg within its scope refers to a type that is derived from itself, that is, the immediate type being defined.
The error in this case is an example of this; while the constraint on AbstractBase<TSelf> rules out incompatible disjoint types, it can't rule out the unintended usage Derived2 : AbstractBase​<Derived1>. As far as AbstractBase is concerned, the supplied type argument Derived1 satisfies its constraint just fine, regardless of which of its subtypes is deriving itself (im-)properly. I've tried everything, for years, to solve TSelf; if anyone knows a trick I've missed, please let me know!
Anyway, there are still a couple other points to mention. For example, unless you can immediately spot the problem in the following code, you'll have to agree that it's a bit dangerous:
public static new String AbstractStaticProp
{
get => AbstractBase<Derived1>.AbstractStaticProp;
set => AbstractBase<Derived2>.AbstractStaticProp = value;
}
Ideally, you want to get the compiler to do what it's meant to, namely, understand that all AbstractStaticProp property instances are related and thus somehow enforce their unification. Since that's not possible for static methods, the only remaining option is to eliminate the extra versions, effectively reducing the problem to the unification of just one, a vacuous operation, obviously.
It turns out that the original code is being too elaborate; the generic-base class approach wants to collapse on the simpler solution all by itself without having to explicitly request it, such as those new-marked properties seem to be doing with the qualification in AbstractBase<Derived1>.​AbstractStaticProp".
You can already refer to each respective independent copy of the static property by qualifying with the derived class name instead (in fact, #Gusman's test harness shows this), so the end result is that the property declarations in the derived class aren't necessary at all. Without further ado, here is the complete simplified version:
abstract class AbstractBase { };
abstract class AbstractBase<TSelf> : AbstractBase
where TSelf : AbstractBase<TSelf>
{
public static String AbstractStaticProp { get; set; }
};
class Derived1 : AbstractBase<Derived1> { };
class Derived2 : AbstractBase<Derived2> { };
This works identically to the code at the top. The test harness gives the same results as before.
static void Test()
{
Derived1.AbstractStaticProp = "I am Derived1";
Derived2.AbstractStaticProp = "I am Derived2";
Debug.Print(Derived1.AbstractStaticProp); // --> I am Derived1
Debug.Print(Derived2.AbstractStaticProp); // --> I am Derived2
}
What you're trying to do is impossible, as others have mentioned.
I'd try something like this
public abstract class ProviderConfiguration : ConfigurationSection
{
public string ConfigurationSectionName { get; set; }
public static ProviderConfiguration Provider { get; set; }
public static Configuration Current
{
get { return (Configuration)ConfigurationManager.GetSection(Provider.ConfigurationSectionName); }
}
}
Then in practice:
public void DoStuff()
{
var provider = new DerivedProviderConfiguration();
ProviderConfiguration.Provider = provider;
}

Categories