Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to programmatically enforce a derived class to pass itself into a base class as the generic type?

Tags:

c#

generics

Basically, I have the following scenario:

public abstract class FooBase<T> where T : FooBase<T>
{
    public bool IsSpecial { get; private set; }

    public static T GetSpecialInstance()
    {
        return new T() { IsSpecial = true };
    }
}

public sealed class ConcreteFooA : FooBase<ConcreteFooA> { ... }
public sealed class ConcreteFooB : FooBase<ConcreteFooB> { ... }

But, the problem I see here is that I could have done ConcreteFooB : FooBase<ConcreteFooA> { ... }, which would completely mess up the class at runtime (it wouldn't meet the logic I'm trying to achieve), but still compile correctly.

Is there some way I haven't thought of to enforce the generic, T, to be whatever the derived class is?


Update: I do end up using the generic parameter, T, in the FooBase<T> class, I just didn't list every method that has it as an out and in parameter, but I do have a use for T.

like image 368
michael Avatar asked May 14 '13 12:05

michael


People also ask

Can derived class objects be assigned to base class?

In C++, a derived class object can be assigned to a base class object, but the other way is not possible.

Can base class access derived class properties?

// As base-class pointer cannot access the derived class variable.


2 Answers

To answer your question:

No, there is no compile time solution to enforce this.

like image 75
Daniel Hilgarth Avatar answered Oct 11 '22 18:10

Daniel Hilgarth


There are a couple of ways to enforce this rule:

  1. Unit Testing - You could write up a unit test (or unit tests) to ensure that the compiled types are passing themselves in as the generic parameter.
  2. Code Analysis - You could create a custom code analysis rule that enforces this, and then set that rule as an error (vs warning). This would be checked at compile-time.
  3. FxCop Rule - Similar to the Code Analysis rule, except if you don't have a version of Visual Studio that has built-in support for Code Analysis, then you can use FxCop instead.

Of course, none of these rules are enforced on a standard compilation, but instead require additional tools (Unit Testing, Code Analysis, FxCop). If someone took your code and compiled it without using these tools you'd run into the same issue... of course, at that point why is someone else compiling your code without running your unit tests or Code Analysis/FxCop rules?


Alternatively, and I don't recommend this, you could throw a run-time error. Why not? According to Microsoft:

If a static constructor throws an exception, the runtime will not invoke it a second time, and the type will remain uninitialized for the lifetime of the application domain in which your program is running.

That really doesn't solve your issue. On top of that, throwing an exception during static initialization is a violation of Code Analysis CA1065:DoNotRaiseExceptionsInUnexpectedLocations. So, you're going in the wrong direction if you do this.

like image 37
myermian Avatar answered Oct 11 '22 17:10

myermian