Derived class instantiation in abstract base class in C# - c#

My aim is to write an abstract base class which contains a method for deriving “child instances”. In this method already some computation is done which is common in all deriving classes.
The difficulty is that the base class is not able to create the child class on its own. So I introduced a type parameter T in my base class and a protected abstract method which shall return an instance of T.
public abstract class Base<T> where T : Base<T>
{
public T GetChild()
{
string param = ComplexComputation();
return NewInstanceFrom(param);
}
protected abstract T NewInstanceFrom(string param);
}
// --- somewhere else: ---
public class Derivative : Base<Derivative>
{
public Derivative() { }
protected sealed override Derivative NewInstanceFrom(string param)
{
return new Derivative(param);
}
private Derivative(string param)
{
// some configuration
}
}
The disadvantage of this approach is that I cannot ensure that NewInstanceFrom is only invoked by the base class. It could also be invoked by classes inheriting from Derivative. That’s what I want to avoid.
So I could encapsulate the functionality in a private class or delegate:
public abstract class Base<T> where T : Base<T>
{
public T GetChild()
{
string param = ComplexComputation();
return subElementDerivator(param);
}
protected Base<T>(Func<string, T> subElementDerivator)
{
this.subElementDerivator = subElementDerivator;
}
private Func<string, T> subElementDerivator;
}
// --- somewhere else: ---
public class Derivative : Base<Derivative>
{
public Derivative()
: base(deriveSubElement)
{
}
private Derivative(string param)
: base(deriveSubElement)
{
// some configuration
}
private static Derivative deriveSubElement(string param)
{
return new Derivative(param);
}
}
But this introduces a new object.
Is there a simpler way to prevent access to a functionality (which the base class shall have access to) from heirs of Derivative?

You can use explicit interface implementation to hide your factory method. Any client can still call the Create method after casting but at least intellisense won't help developers.
public interface ISecretFactory<T>
{
T Create(string param);
}
public abstract class Base<T> where T : Base<T>, ISecretFactory<T>
{
public T GetChild()
{
// We are sure type T always implements ISecretFactory<T>
var factory = this as ISecretFactory<T>;
return factory.Create("base param");
}
}
public class Derivative : Base<Derivative>, ISecretFactory<Derivative>
{
public Derivative()
{
}
private Derivative(string param)
{
}
Derivative ISecretFactory<Derivative>.Create(string param)
{
return new Derivative(param);
}
}
public class SecondDerivative : Derivative
{
public void F()
{
// intellisense won't show Create method here.
// But 'this as ISecretFactory<Derivative>' trick still works.
}
}

The additional object can be avoided by moving the ComplexComputation to the constructor of the base class and making the GetChild method abstract to let the deriving class pick a correct constructor there.
But how to return the computed value param in base constructor to the invoking derivate constructor? A possibility is to use the out parameter modifier. But because in C# 5.0 we are unfortunately not able to declare the variables before (or within) the base constructor call, we need to take the parameter along in the derivative constructor.
public abstract class Base<T> where T : Base<T>
{
public abstract T GetChild();
protected Base(T parent, out string param)
{
param = ComplexComputation();
}
protected Base()
{
}
}
// --- somewhere else: ---
public class Derivative : Base<Derivative>
{
public sealed override Derivative GetChild()
{
string param;
return new Derivative(this, out param);
}
public Derivative() { }
private Derivative(Derivative parent, out string param)
: base(parent, out param)
{
// some configuration
}
}
In my case I could leave the param from the constructors away, instead I stored it in a public property.
This approach except the pesky necessary hack looks relatively clean to me, but it does not “scale” when multiple overloadings of GetChild are necessary.
Maybe in C# 6.0 it is possible to declare the param directly in the base constructor invocation. https://msdn.microsoft.com/de-de/magazine/dn683793.aspx

Related

Use abstract generic type in c# and requires 1 type arguments

Let's say I have follow classes:
public class File { }
public class DB { }
public abstract class Validator<T>
{
T obj;
}
public class FileValidator : Validator<File>
{
}
public class DbValidator : Validator<DB>
{
}
In code I would like to have a ref to abstract class and create certain implementation depends on some condition (like factory).
public class Program
{
static Validator getValidator()
{
//some condition here
return new FileValidator<File>();
}
public static void Main()
{
Validator v = getValidator();
}
}
So, the compiler has a different opinion on this point
Using the generic type 'Validator' requires 1 type arguments
Is there any workaround in this case? Unfortunately, File and DB can't have common interface.
You need a non-generic interface or abstract base-class:
public interface IValidator { ... }
public abstract class Validator<T> : IValidator
{
}
Now you can return IValidator from your method:
static IValidator getValidator()
{
//some condition here
return new FileValidator<File>();
}
public static void Main()
{
IValidator v = getValidator();
}
However be aware that there is no way for the compiler to infer the actual type, which is based upon a runtime-decision.
Apart from this your implementing classes should not be generic at all, only your abstract class should be:
public class FileValidator : Validator<File>
{
}
public class DbValidator : Validator<DB>
{
}

Base() and This() in constructors. (Chained constructors)

I have a question regards chaining constructors I read some question on StackOverflow and some c# articles but I cannot understand the topic fully. So I have a BaseClass that is inherited by DerivedClass. In the DerivedClass, I have no argument constructor but it's calling the base constructor using: base() and it also passing a value. Is this the primary purpose of the base keyword used in the constructor to pass a value to the inherited class from the derived one or is something more out there. And also in the derived class, we have a second constructor that takes 1 parameter and its using: this(). I can't understand why when I remove: this() from this constructor "VS" tells me "There is no argument given that corresponds to the required formal parameter "i" of BaseClass.BaseClass(int) ? Why I can't just have one argument constructor in the DerivedClass without using this()?
public class BaseClass
{
protected int _Num;
public BaseClass(int i)
{
_Num = i;
}
public int Num { get => this._Num ; set => _Num = value; }
}
public class DerivedClassA : BaseClass
{
private string _Name;
private int _AnotherValue;
public string Name { get => this._Name ; set => this._Name = value; }
public int AnotherValue { get => this._AnotherValue; set => this._AnotherValue = value; }
public DerivedClassA() : base(123)
{
_Name = "testing";
}
public DerivedClassA(int param2) : this() <-- Why i can't compile the program without the this() keyword here ?
{
AnotherValue = param2;
}
}
public class Program
{
public static void Main(string[] args)
{
DerivedClassA objA = new DerivedClassA(5);
}
}
I can't find a duplicate that exactly matches, so I'll provide an answer.
Imagine these classes:
public class Base
{
public Base()
{
}
}
public class Derived : Base
{
public Derived()
{
}
}
Try it online
When you initialize a derived class, you have to first initialize the base. In our example above, the Base class has a parameterless constructor, so the derived class can implicitly call it. If we add a base second constructor, this logic remains true, and the parameterless constructor will still be implicitly called:
public class Base
{
public Base()
{
}
public Base(int a)
{
}
}
public class Derived : Base
{
public Derived()
{
}
}
Try it online
But if we take away the parameterless constructor, Derived must now call the base constructor explicitly:
public class Base
{
public Base(int a)
{
}
}
public class Derived : Base
{
public Derived() : base(1)
{
}
}
Try it online
So what happens if we add an extra derived class constructor? Well, that also has to call the base class (either directly, or indirectly):
public class Base
{
public Base(int a)
{
// this method body is executed first
}
}
public class DerivedA : Base
{
public DerivedA(string name, int val) : base(val)
{
// this method body is executed second (last if you used this constructor, e.g. new DerivedA("hello", 1) )
}
public DerivedA() : this("test", 5) // this will call the constructor above, which will first call base. So the final chain is: base, constructor above, this constructor
{
// this method body is executed third (last if you used this constructor, e.g. new DerivedA() )
}
}
public class DerivedB : Base
{
public DerivedB(string name, int val) : base(val)
{
}
public DerivedB() : base(5) // this will call the base constructor, and then this constructor. The constructor above will not be used.
{
}
}
Try it online
Note that all classes have a parameterless constructor when no other constructor is defined, so the following two examples are equivalent:
public class BaseA
{
}
public class BaseB
{
public BaseB()
{
}
}
You'll note that SharpLab shows the compiler removed the empty constructor from BaseB() since it's superfluous.
Finally, a derived class without an explicitly defined constructor, will still call the base class constructor implicitly:
public class Base
{
public Base()
{
// this method body is executed first
Console.WriteLine("Base constructor");
}
}
public class Derived : Base
{
}
Try it online
So to summarise: unless your base class has a parameterless constructor, your derived class constructors have to either call a base constructor directly, or indirectly through another derived class constructor. Obviously you only need to call a single base constructor method, as with any other class instantiation. You don't need matching derived methods for each base method, so long as you can construct the base with the values you do have.

How to override generic method with derived type in c#

I have the following classes:
public interface IService
{
void ApplyChanges<T>(T parameters) where T : ParamBase;
}
public class ServiceBase : IService
{
public virtual void ApplyChanges<T>(T parameters) where T : ParamBase
{ }
}
public abstract class Service : ServiceBase
{
public override void ApplyChanges<T>(T parameters) where T : ParamBase
{
Console.WriteLine(parameters.Param2);
//Apply changes logic here...
}
}
public abstract class ParamBase
{
public string Param1 { get; set; }
}
public class ParamA : ParamBase
{
public string Param2 { get; set; }
}
Here my test main class:
void Main()
{
var service = new Service();
var paramA = new ParamA();
paramA.Param2 = "Test2";
service.ApplyChanges<ParamA>(paramA);
}
What is wrong with that implementation? How can I access parameters.Param2from the overriden ApplyChanges method in my Service class?
The general idea is that I have a ServiceBase and I want to be able for its derived classes to pass different parameter types to the ApplyChanges method.
I'm making a leap here, but it sounds like you intend to have multiple "services", each with an associated parameter type.
Putting a type parameter on the method, as you have done in the example, forces all implementations of that method to be polymorphic. (The technical term for this is higher-rank quantification.)
Instead, you should associate the type parameter with the service itself. This allows a given implementation of the contract to declare which parameter type it's associated with. While you're at it, I wouldn't bother with the base classes or the type bounds.
interface IService<in T>
{
void ApplyChanges(T param);
}
class Param1
{
public int X { get; set; }
}
class Service1 : IService<Param1>
{
public void ApplyChanges(Param1 param)
{
param.X = 123;
}
}
class Param2
{
public int Y { get; set; }
}
class Service2 : IService<Param2>
{
public void ApplyChanges(Param2 param)
{
param.Y = 456;
}
}
You shouldnt impose stronger constraints for method overrides. An overridden method should expand the possible input parameters and reduce the possible outcomes. Otherwise it breaks Liskov Substitution Principle. C# does not allow you to do that.
That said, if you really want it, you could. You won't get compiler warnings in the calling code though. Use that solution if you cannot change the base class.
public class Service<TParam> : Service where TParam : ParamA
{
public override void ApplyChanges<T>(T parameters)
{
Console.WriteLine((parameters as TParam).Param2);
}
}
A better solution would be to add a type parameter to ServiceBase and IService.
public interface IService<TParam>
where TParam : ParamBase
{
void ApplyChanges(TParam parameters);
}
public abstract class ServiceBase<TParam> : IService<TParam>
where TParam : ParamBase
{
public virtual void ApplyChanges(TParam parameters)
{ }
}
public class Service : ServiceBase<ParamA>
{
public override void ApplyChanges(ParamA parameters)
{
Console.WriteLine(parameters.Param2);
}
}
Really, instead of replacing the interface's generic type, it is cleaner to use a "Type Guard". I say cleaner because the interface's method signature stays consistent, and really, what's more important than how your interface is used? (Obviously puppies are more important)
Within the method itself, you can make sure that the type is the one desired as such...
public void Method(ParentRequest req){
if(req is ChildRequest request){
//Do logic here
} else {
throw new Exception($"request is of type {req.GetType().Name} and must be of type ParentRequest");
}
}

C# inherited class from generic as a type

I've got an issue with generics. I've those classes :
abstract class BaseTestClass<T> : where T : class, new()
{
//base test class implementation
public abstract void Run(BaseDataClass<T> data);
}
class BaseDataClass<T> : where T : class, new()
{
//base data class implementation
}
class DataA : BaseDataClass<SettingsA>
{
//some stuff
}
class TestA : BaseTestClass<SettingsA>
{
//Works!
public override void Run(BaseDataClass<SettingsA> data)
{
}
//Doesn't Work!
public override void Run(DataA data)
{
}
}
My question if why can't I use the inherited class in the abstract method ?
[EDIT]
The error at compilation is:
TestA does not implement inherited abstract member Run(BaseDataClass)
You can, but the BaseTestClass<SettingsA> base class simply does NOT have a method to override of the signature Run(DataA), but only one of the signature Run(BaseDataClass<DataA>).
The generic inheritance also means that the generic T type is the same.
You can implement this with an additional generic argument, Type-Safe and without cast:
internal abstract class BaseTestClass<T, Y>
where T : class, new()
where Y : BaseDataClass<T>
{
private T m_data;
//base test class implementation
public abstract void Run(Y data);
}
public class BaseDataClass<T> where T : class, new()
{
}
internal class TestA : BaseTestClass<SettingsA, DataA>
{
public override void Run(DataA data)
{
throw new NotImplementedException();
}
}
class DataA : BaseDataClass<SettingsA>
{
}
class SettingsA
{
}
This is type-safe because the constraint is
where Y : BaseDataClass<T>
If you don't need T directly in you base class, you can only use one generic parameter and remove T
Your second method does not compile because there is no method to be overriden by it, removing the override modificator will make your code compile.
If you want to have a method which will run only when the parameter is of type DataA, but still execute the interface method implementation, you can do this way:
class TestA : BaseTestClass<SettingsA>
{
//Works!
public override void Run(BaseDataClass<SettingsA> data)
{
}
public void Run(DataA data)
{
//dp some stuff
Run((BaseDataClass<SettingsA>)data);
}
}
But note that this is not bullet proof, you could miss boxed calls, the better way is do this way:
class TestA : BaseTestClass<SettingsA>
{
//Works!
public override void Run(BaseDataClass<SettingsA> data)
{
var myDataA = data as DataA;
if (myDataA != null)
{
//your parameter is a DataA;
}
}
}
It does not work because you cannot override one method with two methods. Take the override off of one of the methods in TestA, and it will all work. There's no point in overriding a single method twice, anyhow, within a single class.

Generic factory - expect certain constructor

I want to provide a factory for a certain type of class restricted by a generic constraint, however I need to make sure that the product to create has a certain constructor in order to make my factory work.
public interface IFactory<TProduct>
where TProduct: class, IMyRestriction
{
TProduct Create();
}
Class which implements IMyRestriction:
public class MyRestriction : IMyRestriction {
public MyRestriction(IArgumentType1 arg1, IArgumentType2 arg2) {
...
}
}
which would make this work...
public class MyFactory<TProduct> : IFactory<TProduct>
where TProduct: class, IMyRestriction
{
public TProduct Create() {
// args provided by factory constructor
Activator.CreateInstance(typeof(TProduct), arg1, arg2);
}
}
... however not for a class like this:
public class MyDerivedRestriction : MyRestriction {
public MyDerivedRestriction()
: base(null, null)
{
}
}
The only way I'm able to restrict on a certain constructor using generics is with the new() constraint, but that doesn't make sense in this case.
You've essentially answered your own question -as you know the only type of constraint controlling the constructer is a parameterless one.
The only option left then is to use some sort of Initialization method in place of a constructor, and the logic you would usually do in the constructor do in the Init method
interface IMyRestriction
{
// use whichever arguments you wanted for construction
void Init(string myParam1, string myParam2)
}
public class MyFactory<TProduct> : IFactory<TProduct>
where TProduct: class, IMyRestriction, new()
{
public TProduct Create() {
TProduct p = new TProduct();
p.Init(arg1,arg2);
return p;
}
}
If you need to create different classes with different constructor signatures, you are probably looking for an Abstract Factory pattern, where each entity class has its own implementation of the Factory interface:
#region Restriction Types
public class MyRestriction : IMyRestriction {
public MyRestriction(IArgumentType1 arg1, IArgumentType2 arg2) {
...
}
}
public class MyDerivedRestriction : MyRestriction {
public MyDerivedRestriction()
: base(null, null)
{
}
}
#endregion
#region Factory interface
public interface IFactory<TProduct>
where TProduct: class, IMyRestriction
{
TProduct Create();
}
#endregion
#region Factory implementations for each entity
public class MyRestrictionFactory : IFactory<MyRestriction>
{
public MyRestriction Create()
{
// args provided by factory constructor
return new MyRestriction(arg1, arg2);
}
}
public class MyDerivedRestrictionFactory : IFactory<MyDerivedRestriction>
{
public MyDerivedRestriction Create()
{
return new MyDerivedRestriction();
}
}
#endregion
This may seem like creating more code, but each factory class can be tiny, plus it provides more type-safety and is more flexible, as the factory can deal with the idiosyncrasies of its entity.
As an extension of this pattern, people often add interfaces for each factory, to make it nicer to register in an IOC container and provide more abstraction, but you may not need this in your case. For example:
// this gets resolved in DI, so the IFactory<T> part is abstracted away
public interface IMyRestrictionFactory
{
MyRestriction Create();
}
public class MyRestrictionFactory : IFactory<MyRestriction>, IMyRestrictionFactory
{
public MyRestriction Create()
{
// args provided by factory constructor
return new MyRestriction(arg1, arg2);
}
}
In C# you can't put generic constraints, which define desired signature of constructor, except new() (parameterless constructor).
The best you can do here is either rely on run-time exceptions, or re-write initialization logic to use properties of IMyRestriction instead of constructor arguments:
interface IMyRestriction
{
IArgumentType1 Property1 { get; set; }
IArgumentType2 Property2 { get; set; }
}
public class MyFactory<TProduct> : IFactory<TProduct>
where TProduct : class, IMyRestriction, new()
{
public TProduct Create()
{
var product = new TProduct();
product.Property1 = arg1;
product.Property2 = arg2;
return product;
}
}

Categories

Resources