Casting to arbitrary version of generic class - c#

I have a class as follows:
public class Impactable<T> : where T : Spawnable<T>
{
protected T spawnable = Spawnable<T>.Instance;
void DoSomethingIndependentOfT(){}
}
The reason I have it implemented like this is because Spawnable is a Lazy extendable Singleton. In Impactable, I have of course methods that utilize spawnable, but also methods that don't that I'd like to access externally by casting.
public sealed class EnemySpawnable : Spawnable<EnemySpawnable>
{
}
public class MyEnemyA : Impactable<EnemySpawnable>
{
}
MyEnemyA enemy = new MyEnemyA();
Impactable x = enemy;
x.DoSomethingIndependentOfT();
Is it possible to achieve a cast like this in C# or will I have to re-engineer my code?

No, its not. The type argument constraint on Impactable (where) prevents it. But the refactoring required is non-breaking and trivial. The solution is to promote the type-independent methods to a base class which does not require specialization, like so:
public class Spawnable<T>
{
public static T Instance;
}
public class Impactable
{
internal void DoSomethingIndependentOfT() { }
}
public class Impactable<T> : Impactable where T : Spawnable<T>
{
protected T spawnable = Spawnable<T>.Instance;
}
public sealed class EnemySpawnable : Spawnable<EnemySpawnable>
{
}
public class MyEnemyA : Impactable<EnemySpawnable>
{
}
public class Program
{
public static void Main()
{
MyEnemyA enemy = new MyEnemyA();
Impactable x = enemy;
x.DoSomethingIndependentOfT();
}
}
Even if what you intended would be possible (or is made possible in future versions of C#), it's still much cleaner to do it this way, because it self-documents the intent (methods that do not use generics, should not reside in a container scoped to a constrained type).

Related

Trying to program to abstractions in C# but neither interfaces nor classes really work

I've been trying to apply SOLID principles more consciously on my current project. Using interfaces to create the abstraction and allowing classes that are handling the dependency injection to provide the concretions has really helped with decoupling some of the code and (hopefully!) making it more maintainable in the long run.
However, here and there I'm hitting a bit of a wall where it seems neither interfaces nor abstract classes work for the reason that there are functions for which I want an implementation defined.
This means:
Interfaces will not work since I can't define an implementation and obviously don't want to repeat the code in all implementing classes
Abstract classes will not work because I cannot derive from multiple classes
Some super simple code to illustrate the problem:
public abstract class Vehicle
{
public void MoveForward()
{
// Some code here
// This implementation is always the same
}
public abstract void PerformUniqueAbility(); // This is for the derived class to implement
}
public abstract class RadioSignalBroadcaster
{
public void StartBroadcast()
{
// Some code here
// This implementation is always the same
}
public abstract void PerformUniqueBroadcastingAbility(); // This is for the derived class to implement
}
Now of course what I'd like to do is this:
public class MyNewClass: Vehicle, RadioSignalBroadcaster
{
// Class that contains the implementations for both MoveForward() AND StartBroadcast() but also allows me to define
// bodys for the abstract methods
public override void PerformUniqueAbility()
{
// class specific code here
}
public override void PerformUniqueBroadcastingAbility()
{
// class specific code here
}
}
Of course I cannot do this because of the error:
Error CS1721 Class 'MyNewClass' cannot have multiple base classes: 'Vehicle' and 'RadioSignalBroadcaster'
What's the best way to approach these scenarios?
You could use interfaces with default implementations which were introduced in C# 8. Then you could derive from these interfaces.
Here's an example of how you could you provide default implementations for the MoveForward() and StartBroadcast() methods:
public interface IVehicle
{
void MoveForward()
{
// your code
}
void PerformUniqueAbility();
}
public interface IRadioSignalBroadcaster
{
void StartBroadcast()
{
// your code
}
void PerformUniqueBroadcastingAbility();
}
You can't inherit more than 1 class but you can inherit more than one interface. Is this what you are looking for?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
internal class Program
{
static void Main(string[] args)
{
IVehicle vehicle = new Vehicle();
IRadioBroadcaster broadcaster = new RadioBroadcaster();
vehicle.MoveForward();
vehicle.PerformUniqueAbility();
broadcaster.StartBroadcast();
broadcaster.PerformUniqueAbility();
}
}
public interface IUniqueAbillity
{
void PerformUniqueAbility();
}
public interface IVehicle: IUniqueAbillity
{
void MoveForward();
}
public interface IRadioBroadcaster : IUniqueAbillity
{
void StartBroadcast();
}
public abstract class RealWorldObject : IVehicle, IRadioBroadcaster
{
public void MoveForward()
{
// Move forward
}
public abstract void PerformUniqueAbility();
public void StartBroadcast()
{
// Start broadcast
}
}
public class Vehicle : RealWorldObject, IVehicle
{
public override void PerformUniqueAbility()
{
// Do something
}
}
public class RadioBroadcaster : RealWorldObject, IRadioBroadcaster
{
public override void PerformUniqueAbility()
{
// Do something
}
}
}
C# classes can only inherit from one base class, but can inherit from any number of interfaces.
If your goal is to have multiple base classes being inherited to MyNewClass, you could change one of your abstract classes to inherit from the other, for example:
public abstract class RadioSignalBroadcast : Vehicle
{
// Implementation goes here
}
public class MyNewClass : RadioSignalBroacast
{
// Implementation goes here
}
However, as you can see from this approach, it violates Single Responsibility Principle as now RadioSignalBroadcast (and now MyNewClass) has more than one reason to change (if there's a change to Vehicle or RadioSignalBroadcast logic). Any change that happens to any of the base classes will propagate to all other classes which inherit from those base classes, which may or may not be what you're after.
What's the best way to approach these scenarios?
That entirely depends on the design of your application. Questions to ask yourself:
Do you require Vehicle and RadioSignalBroadcast to be abstract classes, or can it easily be an interface? By the looks of your implementation, you have a couple of methods which you want to share to your derived classes so I understand you wanting to keep them as base classes, but it's something to keep in mind. Also check out if the implementation of MoveForward and StartBroadcast can have a default interface implementation.
Does MyNewClass need to implement both base classes/interfaces? Couldn't two separate classes work out better? Separating out classes like this helps to focus each of the classes to have one single responsibility.
If MyNewClass is not truly a Vehicle or a RadioSignalBroadcast (as per the previous point), can this object be composed by a combination of either of the two, for example:
public class MyNewClass : Vehicle
{
private readonly RadioSignalBroadcast radio;
public MyNewClass(RadioSignalBroadcast radio)
{
this.radio = radio;
}
public void DoStuff()
{
// Do Stuff
this.radio.PerformUniqueBroadcastingAbility();
}
// Implementation goes here
}
Let me know if you want example or more points to point out.
I think Jonas gave you the best answer that you can use default interface implementations. However I keep my post, because it gives information, how to achieve same effect, using technology without this language feature.
public abstract class Example : IExample
{
private readonly IVehicle vehicle;
private readonly IRadioSignalBroadcaster;
public Example(IVehicle vehicle, IRadioSignalBroadcaster radioSignalBroadcaster)
{
this.vehicle = vehicle;
this.radioSignalBroadcaster = radioSignalBroadcaster;
}
public void MoveForward() => vehicle.MoveForward();
public void StartBroadcast() => radioSignalBroadcaster.StartBroadcast();
public void PerformUniqueAbility() => vehicle.PerformUniqueAbility();
public void PerformUniqueBroadcastingAbility() => radioSignalBroadcaster.PerformUniqueBroadcastingAbility();
}
public interface IExample : IVehicle, IRadioSignalBroadcaster
{
}
public interface IVehicle
{
void MoveForward();
void PerformUniqueAbility();
}
public interface IRadioSignalBroadcaster
{
void StartBroadcast();
void PerformUniqueBroadcastingAbility();
}
public abstract class Vehicle : IVehicle
{
public void MoveForward()
{
// ...
}
public abstract void PerformUniqueAbility();
}
public interface ICustomVehicle : IVehicle
{
}
public class CustomVehicle : Vehicle, ICustomVehicle
{
public void PerformUniqueAbility()
{
// ...
}
}
public abstract class RadioSignalBroadcaster : IRadioSignalBroadcaster
{
public void StartBroadcast()
{
// ...
}
public abstract void PerformUniqueBroadcastingAbility();
}
public interface ICustomRadioSignalBroadcaster : IRadioSignalBroadcaster
{
}
public class CustomRadioSignalBroadcaster : RadioSignalBroadcaster, ICustomRadioSignalBroadcaster
{
public void PerformUniqueBroadcastingAbility()
{
// ...
}
}
You will create another classes like that:
public class CustomExample : Example, ICustomExample
{
public CustomExample(ICustomVehicle customVehicle, ICustomRadioSignalBroadcaster customRadioSignalBroadcaster) : base(customVehicle, customRadioSignalBroadcaster)
{
}
}
public interface ICustomExample : IExample
{
}

Cannot access inherited property if class has nested class of same name

I want to access a property of some class of mine, but get compiler error "CS0572 - Cannot reference a type through an expression".
I have the following setup
public interface IHelper {
void DoHelp();
}
public abstract class ClassWithHelperBase<THelper> where THelper : IHelper {
public THelper Helper { get; }
}
public class ClassWithHelper : ClassWithHelperBase<ClassWithHelper.Helper> {
// use a nested class, since there will be n classes deriving from ClassWithHelper and giving each helper a readable name (in this example ClassWithHelperHelper) is ugly
public class Helper : IHelper {
public static void SomeStaticMethod() { }
public void DoHelp() { }
}
}
public class Test {
private ClassWithHelper myClass;
public void DoTest() {
((ClassWithHelperBase<ClassWithHelper.Helper>) myClass).Helper.DoHelp(); // this works, but is ugly
myClass.Helper.DoHelp(); // what I want, but it's not working
//myClass.Helper.SomeStaticMethod(); // funnily IDE supposes static methods here even though the resulting code is invalid, since I am (obviously) not referencing the class type
}
}
The interface is unnecessary for reproduction, I added it for clarity.
Note: I do not want to call a static method, I just added it, to show the IDE mixes up the member and the class qualifier.
Is there a way to access the property Helper of myClass, without casting myClass or renaming the nested class?
Aka: Why can't the compiler distinguish the member and the nested class?
The problems is due to name collision between Helper class (type) and Helper property. Try this
public interface IHelper
{
void DoHelp();
}
public abstract class ClassWithHelperBase<THelper> where THelper : IHelper
{
public THelper Helper { get; set; }
}
public class ClassWithHelper : ClassWithHelperBase<ClassWithHelper.CHelper>
{
// use a nested class, since there will be n classes deriving from ClassWithHelper and giving each helper a readable name (in this example ClassWithHelperHelper) is ugly
public class CHelper : IHelper
{
public static void SomeStaticMethod() {}
public void DoHelp() { }
}
}
public class Test
{
private ClassWithHelper myClass;
public void DoTest() {
myClass.Helper.DoHelp();
ClassWithHelper.CHelper.SomeStaticMethod();
}
}
Here I renamed Helper class to the CHelper, so compiler can now distinguish class and property and thus the line myClass.Helper.DoHelp(); now works without cast.
If a "do not rename nested class" requirement is absolutely mandatory, then the problem may be also solved by renaming the Helper property in the base class to avoid name collision. However, I can't imagine better name for the property.
Unfortunately, for the static method, you can't reference myClass instance. So, you will need reference the whole type.

How to require an implementation of an abstract class in C#?

I want to build a class that would have a property, in which there is an instance of a class, which implements an abstract class. Here's and example.
public class MyClass {
public MyDerivedClassA derived;
public void mainClassUtility () {
derived.foo();
}
}
public abstract class MyAbstractBaseClass {
public abstract void foo();
}
public class MyDerivedClassA : MyAbstractBaseClass {
public override void foo(){
return;
}
}
public class MyDerivedClassB : MyAbstractBaseClass
{
public override void foo()
{
return;
}
}
Basically, I want to make sure the object I'm using is derived from an abstract class and implements all the methods I will need to use. There will be many implementations of the abstract class and depending on the current state of the program, MyClass might be using different implementations of the ABC. I want to write the program in a way, that no matter what implementation of the ABC is currently being used, there is a way to call it's methods by MyClass. What would be the best solution to this problem?
Unless I'm misunderstanding the question, you're pretty much there. Have MyClass expect a property of the abstract base class and you should be all set.
using System;
public class Program
{
public static void Main()
{
var myClassOne = new MyClass(new MyDerivedClassA());
var myClassTwo = new MyClass(new MyDerivedClassB());
myClassOne.mainClassUtility();
myClassTwo.mainClassUtility();
}
public class MyClass
{
public MyAbstractBaseClass Derived;
public MyClass(MyAbstractBaseClass derived)
{
Derived = derived;
}
public void mainClassUtility ()
{
Derived.foo();
}
}
public abstract class MyAbstractBaseClass
{
public abstract void foo();
}
public class MyDerivedClassA : MyAbstractBaseClass
{
public override void foo()
{
Console.WriteLine("I am MyDerivedClassA");
return;
}
}
public class MyDerivedClassB : MyAbstractBaseClass
{
public override void foo()
{
Console.WriteLine("I am MyDerivedClassB");
return;
}
}
}
How to require an implementation of an abstract class in C#?
You can not instantiate a abstract class - and thus can not use it for most cases. Except as variable/argument/generic type argument. You need to make a concrete (non-abstract) class that inherits from it. You can only use the abstract class as a variable/argument type. To guarantee that only stuff that inherits from it can be used there.
Basically, I want to make sure the object I'm using is derived from an abstract class and implements all the methods I will need to use.
Then use the abstract class as type argument. It means only instaces of the abstract class (of wich there can be no instance) or instances of classes that inherit from it (that somebody else writes) can be used at that place.
Note that Abstract classes and Interfaces overlap in nearly all uses. There is a miriad small differences, but I do not think they mater. The only big difference I can see, is one of exclusivity:
a class can implement as many Interfaces as it wants.
You can only inherit from one abstract class. that means it is for a primary, exclusive purpose. That way you prevent some dumb ideas, like someone trying to make a Windows Form that is also a DBConnection.

Instantiating a generic field of a class

Is there a way to have a generic field in a class to specialize to a specific type in the constructor?
For example:
class concreteClass1
{
private int a;
public concreteClass1( int a)
{
this.a = a;
}
}
class concreteClass2
{
string b;
public concreteClass2(string b)
{
this.b = b;
}
}
class A<T>
{
private T field;
public A(int x)
{
field = new concreteClass1(x); //error here CS0029
}
public A(string y)
{
field = new concreteClass2(y); //error here CS0029
}
}
So T can be either concreteClass1 or concreteClass1 and their respective ctors will have different signatures.
I would refactor this to use dependency injection. That way the class doesn't contain code to create other classes that it depends on, like myConcreteField = new ConcreteA<T>(4);. Dependency injection is used to keep code from getting tied into difficult knots like this.
(Your example is very, very abstract, which makes it a little difficult. If you use class names like "Concrete" and "Implementation" then it makes the answer harder to read because we use those same words to describe concepts.)
Instead, whatever that Concrete thing is, declare an interface, like
public interface ISomethingThatTheOtherClassNeeds<T>
{
public int MySomething {get;set;}
}
public class SomethingThatTheOtherClassNeeds : ISomethingThatTheOtherClassNeeds<string>
{
public int MySomething {get;set;}
}
Then in your Implementation class:
class Implementation<T>
{
private readonly ISomethingThatTheOtherClassNeeds<T> _something;
public Implementation(ISomethingThatTheOtherClassNeeds<T> something)
{
_something = something;
}
void DoSomething()
{
Console.Write(_something.MySomething.ToString());
}
}
The difference is that instead of being responsible for creating whatever that class is, it's passed to Implementation in the constructor. Implementation doesn't even know what the class is - it just knows that it matches the interface.
This is especially helpful if those other classes in turn depend on more classes. If you're creating them by calling new in your class then that class has to know how to create those classes.
Then to wire it up you would use a dependency injection container like Windsor, Unity, Autofac, and many more. That's not very commonly done with console applications, but I'm guessing this is more experimental than real.
Well this was a bit tricky due to having to convert types. Maybe this will work for you?
class Program
{
static void Main(string[] args)
{
var myImplementation = new Implementation<int>(4);
var myImplementation2 = new Implementation<string>("Hello World");
Console.WriteLine(myImplementation.myConcreteField); // outputs 4!
Console.WriteLine(myImplementation2.myConcreteField); // outputs Hello World
}
}
abstract class MyAbstract<T>
{
public T MySomething;
public MyAbstract(T something)
{
MySomething = something;
}
}
class ConcreteA<T> : MyAbstract<T>
{
public ConcreteA(int something) : base((T)Convert.ChangeType(something, typeof(T)))
{
}
}
class ConcreteB<T> : MyAbstract<T>
{
public ConcreteB(string something) : base((T)Convert.ChangeType(something, typeof(T)))
{
}
}
class Implementation<T>
{
public MyAbstract<T> myConcreteField;
public Implementation(T a)
{
myConcreteField = new ConcreteA<T>(4);
}
void DoSomething()
{
Console.Write(myConcreteField.MySomething.ToString());
}
}

Force a child class to pass itself as the Generic parameter to the base class

I want to force my child classes to pass themselves as as the generic parameter to the parent class.
For example :
class BaseClass<T> where T: BaseClass
{
//FullClassName : Tuple [Save,Update,Delete]
Dictionary<string,Tuple<delegate,delegate,delegate>> dict = new Dictionary...;
static BaseClass()
{
RegisterType();
}
private static void RegisterType()
{
Type t = typeof(T);
var props = t.GetProperties().Where(/* Read all properties with the SomeCustomAttribute */);
/* Create the delegates using expression trees and add the final tuple to the dictionary */
}
public virtual void Save()
{
delegate d = dict[t.GetType().FullName];
d.Item1(this);
}
}
class ChildClass : BaseClass<ChildClass>
{
[SomeCustomAttribute]
public int SomeID {get;set;}
[SomeCustomAttribute]
public string SomeName {get; set;}
}
public class Program
{
public static void Main(string[] args)
{
ChildClass c = new ChildClass();
c.Save();
}
}
Obviously the above code won't compile. I'll restate : I want the child class to pass itself as the generic parameter and not any other child of BaseClass.
(The above code is kind of a psuedo code and will still not compile).
You can do this:
public class BaseClass<T> where T: BaseClass<T> { }
public class ChildClass : BaseClass<ChildClass> { }
But this doesn't force you to use ChildClass as the generic parameter. You could do this public class OtherChildClass : BaseClass<ChildClass> { } which would break the "coontract" that you want to enforce.
The direct answer is that if your accessing a static method then typeof(T) will give you the type for reflection.
However, there is probably better solutions than using reflection. Options:
1) Static constructor on the child class.
2) Abstract method declared in the base class.
I do not know the application, but I get concerned about my design if I feel like using a static constructor, I also get concerned if a base class needs to initialize the child class.
I suggest looking at injection as a solution rather than inheritance. It offers superior unit testing and often a better architecture.
More info (after initial post), this is my preferred solution:
public interface IRegesterable
{
void Register();
}
public class Widget : IRegesterable
{
public void Register()
{
// do stuff
}
}
public class Class1
{
public Class1(IRegesterable widget)
{
widget.Register();
}
}
Hope this helps
The ConcurrentDictionary is being used as a Set<Type>. We can check in the Set<Type> if the type has been initialized. If not we run RegisterType on the type.
public abstract class BaseClass
{
//Concurrent Set does not exist.
private static ConcurrentDictionary<Type, bool> _registeredTypes
= new ConcurrentDictionary<Type, bool>();
protected BaseClass()
{
_registeredTypes.GetOrAdd(GetType(), RegisterType);
}
private static bool RegisterType(Type type)
{
//some code that will perform one time processing using reflections
//dummy return value
return true;
}
}
public class ChildClass : BaseClass
{
}
There are several inefficiencies with this pattern though.
object.GetType() is pretty darn slow, and inefficient.
Even with the HashSet behavior, we are checking for initialization on each instanciation. Its as fast as I can get it, but its still pretty superfluous.

Categories

Resources