Alternative to traits - c#

I'm quite new to C# coming from PHP and I have encountered a problem for which traits would be perfect but I understand that C# doesn't support traits. What is the best way to solve this?
In Godot I'd like to make the animation a bit easier on myself by adding a few methods for animation, according to PHP I'd do something like this. The methods can't really be static either.
public trait SpriteAnimator {
public void Animate(string animation)
{
// DO SOMETHING
}
}
public class Actor : KinematicBody2D
{
use SpriteAnimator;
public override void _Ready()
{
Animate("run");
}
}
How would I solve this in C#?

C# does not have anything that is completely analogous to PHP's trait system but some aspects of it can be emulated using interfaces, Extension Methods and occasionally Default Interface Methods.
The simplest usage of trait is to add methods to classes without subclassing. Extension methods allow you to effectively add methods to objects based on their type. Only members that are publicly visible on the targetted type will be accessible in the extension.
public interface INamed
{
string Name { get; }
}
public static class DemoExtensions
{
// This is available on instances of any type
public static void SayHello(this object self)
{
Console.WriteLine("Hello.")
}
// This one will work on instances whose type implements INamed
public static void SayHello(this INamed self)
{
Console.WriteLine($"Hello {self.Name}.");
}
}
Static trait data members are more difficult. While you can define a static field or property in the extension class (DemoExtensions above) the value is shared among all types that the extension method runs on. If you need static values based on the type of object the method is called against then you'll need to handle that manually with a Dictionary<type, ...> static in the extension class.
Another limitation is that extension methods require an object to invoke:
public class MyClass : INamed
{
public string Name { get; }
public MyClass(string name)
{
Name = name;
}
public void DoSomething()
{
this.SayHello();
}
}
Note the this.SayHello(); line in DoSomething. If you take the this. portion away the program will not compile.
Default Interface Methods can also be used as a sort of extension, but you have to force cast the type to the interface before you can access them. No more this.SayHello();, now it's ((INamed)this).SayHello(); and that's not even the worst of it. They have their place but mostly it's not useful to me. Your milage may vary.
As of C#9 there is no way to add extension types other than methods, and I very strongly doubt that we'll get Extension Properties at any point in the future. You'll have to figure your own way around trait properties until that changes.

Related

Why can't interfaces specify static methods?

I know this question has been asked over and over, but I can't seem to find good enough answers. So to make it clear what I'm trying to know, I'll split this in two questions:
Why can't interfaces have static method signatures? I'll try to preempt the non-answers asking why in the world I would want to do this with the following: I would want to be able to statically invoke GetDbConnectionType() on SqliteCodeGenerator and MssqlCodeGenerator:
interface ICodeGenerator
{
// this is the method I would like to be static:
string GetDbConnectionType();
}
abstract class CodeGeneratorBase : ICodeGenerator
{
public abstract string GetDbConnectionType();
public void GenerateSomeCode(StringBuilder s)
{
s.AppendLine("var foo = new " + GetDbConnectionType() + "();");
}
}
class SqliteCodeGenerator : CodeGeneratorBase
{
public override string GetDbConnectionType()
{
return "SQLiteConnection";
}
}
class MssqlCodeGenerator : CodeGeneratorBase
{
public override string GetDbConnectionType()
{
return "SqlConnection";
}
}
On the other hand, and this is the matter of this second question, if you know of a good alternative to reach the aforementioned goal, then by all means...
Suppose you could specify in an interface that a type had to have a particular static method... how would you call it? Polymorphism works through instances - whereas static members explicitly don't use instances.
Now, having said that, there's one situation in which I can see static interface members working: generic types. For example:
// This isn't valid code...
public void Foo<T>() where T : ICodeGenerator
{
string type = T.GetDbConnectionType();
}
That would call the static member on the concrete type T.
I've blogged more about this, but I suspect the benefit doesn't justify the complexity.
In terms of alternatives - usually you'd have another interface, and have separate types to implement that interface. That works well in some contexts, but not in others.
#JonSkeet: It's possible to create a static interface member in CIL, so I'm afraid your first statement is misleading. I assume it was omitted from C# as a design choice by the Microsoft team to encourage correct usage of interfaces.
The best way to get this functionality is probably with extension methods, these will allow you to add a method to all inheritors of your interface or to a specific implementation of that interface however you need to write a separate class to hold the implementation of the extension method which (if not planned for) can be easy to lose track of.
Jon's answer covers pretty much everything so my answer only includes a possible work around using the .NET configuration API. It requires a bit of syntax overhead but it does give you static access to the instance.
interface IStorage
{
void Store(string item);
}
static class Storage
{
private static readonly IStorage _instance;
static Storage()
{
var storageTypeString = ConfigurationManager.AppSettings["storageTypeString"];
var storageType = Type.GetType(storageTypeString, true);
_instance = (IStorage)Activator.CreateInstance(storageType);
}
public static void Store(string item)
{
_instance.Store(item);
}
}
It might be somewhat helpful if an interface could specify a static class, such that members of that class would be seen by the compiler as static members of that interface. Thus, instead of having to use static class Enumerable<T> to get Enumerable<T>.Default, one could instead syntactically specify IEnumerable<T>.Default.
It would be even more helpful if an interface could specify that some such static methods should be usable in a fashion similar to extension methods, but without the weird scoping rules associated with them (so an interface could appear to offer multiple "convenience" overloads for some member functions without requiring all of the implementations to provide them).
It would be extremely helpful if, combined with such a feature, interface methods could be declared "optional", such that when an implementation provided a method it would be used, and when it did not the extension-ish method would be automatically substituted. This would probably require changes to the CLR, however.
In any case, because interfaces do not include static classes, the best one can do is provide static classes which users of the interface will find helpful, even though the compiler will regard those classes and the interfaces as entirely independent entities.
I know this is old, but actually you can with static functions declared in a static class outside of a name space.
but they way your putting it you would just make the function static in the abstract class
to do it from an interface you do this
public static class Interfacefunction{
public static string GetDbConnectionType(this ICodeGenerator me)
{
// this is the method I would like to be static:
// you can even get access to me
return "SQLiteConnection";
}
}
A sort of workaround (though it may actually be better this way) for this I've decided to use is to use a static instance instead of a static interface.
Rather than:
// does not compile
ISomeInterface {
static void DoSomething();
static bool TestSomething(string pValue);
// etc...
}
static class SomeStaticClass : ISomeInterface {
public static void DoSomething() {
}
public static bool TestSomething(string pValue) {
}
}
Define a class (make it generic if the logic must vary between classes that you use it with):
sealed class SomeClass {
public void DoSomething() {
// reusable implementation
}
public bool TestSomething(string pValue) {
// reusable implementation
}
}
and give a static instance of that class to your static class:
static class SomeStaticClass {
static readonly SomeClass sSomeClass = new SomeClass();
}
The only issue is that you have to decide whether to expose a property to the static instance:
static class SomeStaticClass {
static readonly SomeClass sSomeClass = new SomeClass();
public static SomeClass SomeProperty { get { return sSomeClass; } }
}
...
SomeStaticClass.SomeProperty.DoSomething();
if (SomeStaticClass.SomeProperty.TestSomething(someValue))
...
or to wrap its methods:
static class SomeStaticClass {
static readonly SomeClass sSomeClass = new SomeClass();
public static void DoSomething() {
sSomeClass.DoSomething();
}
public static bool TestSomething(string pValue) {
sSomeClass.TestSomething(pValue);
}
}
...
SomeStaticClass.DoSomething();
if (SomeStaticClass.TestSomething(someValue))
...

How to write a method that can be shared by two non-inherited class

I am having 2 classes, both having a same method(name + type +behavior) and a same property (name + type)
public class Country
{
public string Name { get; set; }
public void DisplayName()
{
Console.WriteLine(this.Name);
}
}
public class Person
{
public string Name { get; set; }
public void DisplayName()
{
Console.WriteLine(this.Name);
}
}
-- Person and Country classes are not allowed to inherit
In the above code you can see Person class has similar method(DisplayName) like Country class. I am looking for a way so that both classes can share the same method codes, i want to do this because in my real codes- Method which i want to share is very big and whenever i change code in one class i have to copy paste it in other class too. That i feel is not the correct way.
Please suggest how to resolve this problem.
You say they cannot inherit from a common base class, but you could add an interface, right? I suggest giving them each a common interface. Then define an extension method for that interface. The method will appear for each of them in VS.
(Assumption: this will work if the class members accessed by the extension methods are public or internal.)
interface IDisplayable
{
string Name {get; set;}
}
public class Country : IDisplayable
{
public string Name { get; set; }
}
public class Person : IDisplayable
{
public string Name { get; set; }
}
public static void DisplayName(this iDisplayable d)
{
return doSomeDisplayLogic(d.Name);
}
. . . And in the same class as your extension method, define (not as an extension method) a function doSomeDisplayLogic to do your common logic. (first-time gotcha: make sure the extension method is in the same Namespace or the its namespace is also included in the calling code.)
I don't know if you're new to extension methods or not. They are very powerful. (And like many powerful features, they can be abused). An extension method on an interface seems crazy at first, until you get straight in your head how extension methods really work. LINQ wouldn't work without this!
Update: I see your comment above that the classes can't inherit from a common class, because they are already inheriting from a common class (which I assume can't be messed with too much). I would like to point out an Option 2, based on this: Creating a new class that Country/Person/etc. will inherit from, that itself inherits from the existing common parent class. The existing base class would become a grandparent class, so to speak. This would become more the route to go if Country and Person have other common characteristics besides this DisplayName method. If DisplayName is all you're after, the Interface/Extension pattern might be better.
Define an interface
public interface INameable
{
string Name {get;}
}
then add an extension
public static class INameableExt
{
public static void DisplayName(this INameable n)
{
// do your thing
}
}
I would suggest to avoid Extension Methods in some cases, you can ran into a problem when you need slightly a different implementation for both classes and then you have to design a more generic solution, EM can cause the same issues like multiple inheritance does.
As more generic OOD solution I would suggest to extract this behaviour into a separate service class abstracted by an interface:
public interface IDisplayService()
{
void Display();
}
Then implement it and inject into both classes via constructor.
Also, instead of introducing the interfaces and new classes you can inject Action or Func<> via constructor or even property and then call this method by invoking an injected in delegate.
You could create either a static utility method DisplayName() that you pass the data needed for display, or use composition and move all properties and corresponding methods such as DisplayName() in a separate class - then use an instance of this class from both Country and Person.
You could implement a strategy pattern:
class DisplayNameStrategy<T> {
private readonly Func<T, string> nameSelector;
public void DisplayNameStrategy(Func<T, string> nameSelector) {
this.nameSelector = nameSelector;
}
public void abstract DisplayName(T t);
}
class WriteToConsoleDisplayNameStrategy<T> : DisplayNameStrategy<T> {
public void WriteToConsoleDisplayNameStrategy(Func<T, string> nameSelector)
: base(nameSelector) { }
public override void DisplayName(T t) {
Console.WriteLine(this.nameSelector(t));
}
public class Person {
private readonly DisplayNameStrategy<Person> displayNameStrategy =
new WriteToConsoleDisplayNameStrategy<Person>(x => x.Name);
public string Name { get; set; }
public void DisplayName() {
this.displayNameStrategy(this);
}
}
Note: it's probably better to inject the concrete strategy.
You could use composition: define an interface, a class that implements it, and then have Person and Country implement the interface by calling methods on the implementation class:
// the interface
public interface IName {
string Name { get; set; }
void DisplayName();
}
// a class that implements the interface with actual code
public class NameImpl : IName {
public string Name { get; set; }
public void DisplayName() {
Console.WriteLine(this.Name);
}
}
public class Country : IName {
// instance of the class that actually implements the interface
IName iname = new NameImpl();
// forward calls to implementation
public string Name {
get { return iname.Name; }
set { iname.Name = value; }
}
public void DisplayName() {
// forward calls to implementation
iname.DisplayName();
}
}
What I THINK you are asking for is multiple class inheritance which is not allowed in C#. (but can be with C++ which you are NOT doing).
All the others have identified doing an INTERFACE solution, and probably the best way to go. However, from your description, you have a SINGLE BLOCK of code that is identical regardless of the type of object being a person or a business. And your reference to a huge block of code, you don't want to copy/paste that same exact code among all the other classes that may be intended to use similar common "thing" to be done.
For simple example, you have a functionality that builds out a person's name and address (or business name and address). You have code that is expecting a name and up to 3 address lines, plus a city, state, zip code (or whatever else). So, the formatting of such name/address information is the same for a person vs a business. You don't want to copy this exact method over and over between the two. However, each individual class still has its own things that it is responsible for.
I know its a simple example for context, but I think gets the point across.
The problem with just defining an Interface is that it won't allow you to actually implement the CODE you are referring to.
From your sample, I would consider doing a combination of things.. Create a static class with methods on it that you might want as "globally" available. Allow a parameter to be passed into it of an instance of a class that has a type of interface all the others have expressed that will guarantee the incoming object has all the "pieces" of properties / methods you are expecting, and have IT operate on it as needed. Something like
public interface ITheyHaveInCommon
{
string Name;
string GetOtherValue();
int SomethingElse;
}
public class Person : ITheyHaveInCommon
{
// rest of your delcarations for the required contract elements
// of the ITheyHaveInCommon interface...
}
public class Country : ITheyHaveInCommon
{
// rest of your delcarations for the required contract elements
// of the ITheyHaveInCommon interface...
}
public static class MyGlobalFunctions
{
public static string CommonFunction1( ITheyHaveInCommon incomingParm )
{
// now, you can act on ANY type of control that uses the
// ITheyHaveInCommon interface...
string Test = incomingParm.Name
+ incomingParm.GetOtherValue()
+ incomingParm.SomethingElse.ToString();
// blah blah with whatever else is in your "huge" function
return Test;
}
}
warning: lots of untested code here, wild guessing mostly since i disagree with the base assumption "no inheritance".
something like this should help you. create a new static class and paste your code in here.
public static class Display
{
public static void DisplayName<T>(T obj)
{
if ((T is Person) || (T is Country) || (T is whateveryouwant))
{
//do stuff
}
}
}
in your classes, refactor ShowDisplayName() to call that with "this" as parameter.
...
public void DisplayName()
{
DisplayName(this);
}
...
I wonder why your classes are not allowed to inherit it from a base class, since that's imho the right-est way to solve this.
A couple of options:
Make both classes implement an interface for the common members (Name) and add an extension method for the behaviour (or just a normal static method)
Create methods which take an instance and a lambda exppession to access the comment members, e.g.
public static void Display<T>(T item, Func<T, string> nameGetter)
You'd then call it with (say)
DisplayHelper.Display(person, p => p.Name);
The interface solution is the cleaner one, but using a delegate is more flexible - you don't need to be able to change the classes involved, and you can cope with small variations (e.g. PersonName vs FooName vs Name)
You can define that big method in a separate class and then call the method in both the above classes. For a static method, you can call the method using classname.methodname() syntax.
For a non static method, you will have to do this:
classname obj=new classname();
obj.methodname();

Interface wonder question

We define interface as below:
interface IMyInterface
{
void MethodToImplement();
}
And impliments as below:
class InterfaceImplementer : IMyInterface
{
static void Main()
{
InterfaceImplementer iImp = new InterfaceImplementer();
iImp.MethodToImplement();
}
public void MethodToImplement()
{
Console.WriteLine("MethodToImplement() called.");
}
}
instead of creating a interface , why can we use the function directly like below :-)
class InterfaceImplementer
{
static void Main()
{
InterfaceImplementer iImp = new InterfaceImplementer();
iImp.MethodToImplement();
}
public void MethodToImplement()
{
Console.WriteLine("MethodToImplement() called.");
}
}
Any thoughts?
You are not implementing the interface in the bottom example, you are simply creating an object of InterfaceImplementer
EDIT: In this example an interface is not needed. However, they are extremely useful when trying to write loosely coupled code where you don't have to depend on concrete objects. They are also used to define contracts where anything implementing them has to also implement each method that it defines.
There is lots of information out there, here is just a brief intro http://www.csharp-station.com/Tutorials/Lesson13.aspx
If you really want to understand more about interfaces and how they can help to write good code, I would recommend the Head First Design Patterns book. Amazon Link
instead of creating a interface , why
can we use the function directly like
below
Are you asking what the point of the interface is?
Creating an interface allows you to decouple your program from a specific class, and instead code against an abstraction.
When your class is coded against an interface, classes that use your class can inject whichever class they want that implements this interface. This facilitates unit testing since not-easily-testable modules can be substituted with mocks and stubs.
The purpose of the interface is for some other class to be able to use the type without knowing the specific implementation, so long as that type conforms to a set of methods and properties defined in the interface contract.
public class SomeOtherClass
{
public void DoSomething(IMyInterface something)
{
something.MethodToImplement();
}
}
public class Program
{
public static void Main(string[] args)
{
if(args != null)
new SomeOtherClass().DoSomething(new ImplementationOne());
else
new SomeOtherClass().DoSomething(new ImplementationTwo());
}
}
Your example doesn't really follow that pattern, however; if one that one class implements the interface, then there really isn't much of a point. You can call it either way; it just depends on what kind of object hierarchy you have and what you intend to do for us to say whether using an interface is a good choice or not.
To sum: Both snippets you provide are valid code options. We'd need context to determine which is a 'better' solution.
Interfaces are not required, there is nothing wrong with the last section of code you posted. It is simply a class and you call one of it's public methods. It has no knowledge that an interface exists that this class happens to satisfy.
However, there are advantages:
Multiple Inheritance - A class can only extend one parent class, but can implement any number of interfaces.
Freedom of class use - If your code is written so that it only cares that it has an instance of SomethingI, you are not tied to a specific Something class. If tomorrow you decide that your method should return a class that works differently, it can return SomethingA and any calling code will not need to be changed.
The purpose of interfaces isn't found in instantiating objects, but in referencing them. Consider if your example is changed to this:
static void Main()
{
IMyInterface iImp = new InterfaceImplementer();
iImp.MethodToImplement();
}
Now the iTmp object is of the type IMyInterface. Its specific implementation is InterfaceImplementer, but there may be times where the implementation is unimportant (or unwanted). Consider something like this:
interface IVehicle
{
void MoveForward();
}
class Car : IVehicle
{
public void MoveForward()
{
ApplyGasPedal();
}
private void ApplyGasPedal()
{
// some stuff
}
}
class Bike : IVehicle
{
public void MoveForward()
{
CrankPedals();
}
private void CrankPedals()
{
// some stuff
}
}
Now say you have a method like this somewhere:
void DoSomething(IVehicle)
{
IVehicle.MoveForward();
}
The purpose of the interface becomes more clear here. You can pass any implementation of IVehicle to that method. The implementation doesn't matter, only that it can be referenced by the interface. Otherwise, you'd need a DoSomething() method for each possible implementation, which can get messy fast.
Interfaces make it possible for an object to work with a variety of objects that have no common base type but have certain common abilities. If a number of classes implement IDoSomething, a method can accept a parameter of type IDoSomething, and an object of any of those classes can be passed to it. The method can then use all of the methods and properties applicable to an IDoSomething without having to worry about the actual underlying type of the object.
The point of the interface is to define a contract that your implementing class abides by.
This allows you to program to a specification rather than an implementation.
Imagine we have the following:
public class Dog
{
public string Speak()
{
return "woof!";
}
}
And want to see what he says:
public string MakeSomeNoise(Dog dog)
{
return dog.Speak();
}
We really don't benefit from the Interface, however if we also wanted to be able to see what kind of noise a Cat makes, we would need another MakeSomeNoise() overload that could accept a Cat, however with an interface we can have the following:
public interface IAnimal
{
public string Speak();
}
public class Dog : IAnimal
{
public string Speak()
{
return "woof!";
}
}
public class Cat : IAnimal
{
public string Speak()
{
return "meow!";
}
}
And run them both through:
public string MakeSomeNoise(IAnimal animal)
{
return animal.Speak();
}

C# interface static method call with generics

Is there a simple way to implement this, and if possible without instanciating an object :
interface I
{
static string GetClassName();
}
public class Helper
{
static void PrintClassName<T>() where T : I
{
Console.WriteLine(T.GetClassName());
}
}
Try an extension method instead:
public interface IMyInterface
{
string GetClassName();
}
public static class IMyInterfaceExtensions
{
public static void PrintClassName<T>( this T input )
where T : IMyInterface
{
Console.WriteLine(input.GetClassName());
}
}
This allows you to add static extension/utility method, but you still need an instance of your IMyInterface implementation.
You can't have interfaces for static methods because it wouldn't make sense, they're utility methods without an instance and hence they don't really have a type.
You can not inherit static methods. Your code wouldn't compile in any way, because a interface can't have static methods because of this.
As quoted from littleguru:
Inheritance in .NET works only on
instance base. Static methods are
defined on the type level not on the
instance level. That is why overriding
doesn't work with static
methods/properties/events...
Static methods are only held once in
memory. There is no virtual table etc.
that is created for them.
If you invoke an instance method in
.NET, you always give it the current
instance. This is hidden by the .NET
runtime, but it happens. Each instance
method has as first argument a pointer
(reference) to the object that the
method is run on. This doesn't happen
with static methods (as they are
defined on type level). How should
the compiler decide to select the
method to invoke?
I also tried to setup a static method on an interface a little while ago, not sure why now. I did bookmark this so maybe it helps:
Interface with a static method by using extension methods
If you're just after the type name, you can just do this:
public class Helper
{
static void PrintClassName<T>()
{
Console.WriteLine(typeof(T).Name);
}
}
Declaring a static property, event or method on an interface definition is not considered a legal definition. This is because interfaces are considered contracts and as such, represent something that will be implemented by every client instance of that interface.
A static declaration essentially states that the static member does not require a physical client implementation in order to execute the required functionality and this falls short of the general concept of interfaces: providing a proven contract.
The answer is a qualified "not really but Sort Of". You can provide a static extension method to all implementors of a given interface and can then call this from your implementer in a property or another method. As an example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace InterfacesWithGenerics
{
class Program
{
static void Main(string[] args)
{
Helper.PrintClassName<Example>(new Example());
Console.ReadLine();
}
}
public class Example : I
{
#region I Members
public string ClassName
{
get { return this.GetClassName(); }
}
#endregion
}
public interface I
{
string ClassName { get; }
}
public class Helper
{
public static void PrintClassName<T>(T input) where T : I
{
Console.WriteLine( input.GetClassName()) ;
}
}
public static class IExtensions
{
public static string GetClassName(this I yourInterface)
{
return yourInterface.GetType().ToString();
}
}
}
Here we have an interface (I) which defines the property we care about and a static extension method (GetClassName) which is applied to all members of its type which does the grunt work of getting the information we want. We Have a Class (Example) which implements the I interface so when we call our static helper class passing in an instance of Example, it runs the static method against it. Unfortunately it is not valid to reference the type T directly within the method itself as a variable, you'll have to pass an instance into the application.
You could define the className as attribute on the specific class. This is the preferred ay to store metadata in .net. This way you can query the attribute for the given class and you do not need an instance.
Yes, you can - sort-of - if you don't mind defining new types that proxy instance calls to static methods:
While an interface can only declare instance members, you can use a couple of simple tricks with C#'s generics, without needing reflection, to accomplish what you're after (and without resorting to Java-style AbstractFactoryBeanFactory design-pattern overuse).
What we can do, is define a separate struct (i.e. a value-type) that contains instance members that call-into the static members we want.
So if we have this interface:
interface IStaticFunctionality
{
void DoSomethingWithoutAnObjectInstance();
}
...and we want to do something like this:
void AGenericMethodThatDoesntHaveAnInstanceOfT<T>()
{
T.DoSomethingWithoutAnObjectInstance();
}
...then we can do this:
void AGenericMethodThatDoesntHaveAnInstanceOfT<T>()
where T : struct, IStaticFunctionality
{
T t = default;
t.DoSomethingWithoutAnObjectInstance();
// Note the above code uses `T t default;` instead of `T t = new T()`.
// This is because the C# compiler currently replaces `new T()` with `Activator.CreateInstance<T>()` in the generated bytecode.
// This has poor performance compared to `default(T)` or a normal non-generic constructor call, but the compiler does this because it's a workaround for a design-bug back in C# 6.0: https://devblogs.microsoft.com/premier-developer/dissecting-the-new-constraint-in-c-a-perfect-example-of-a-leaky-abstraction/
}
So if we have different types with the static void DoSomethingWithoutAnObjectInstance method, we just need to define struct implementations of IStaticFunctionality for each of those types:
class Foo
{
public static void DoSomethingWithoutAnObjectInstance()
{
Console.WriteLine("foo");
}
struct Static : IStaticFunctionality
{
void DoSomethingWithoutAnObjectInstance() => Foo.DoSomethingWithoutAnObjectInstance();
}
}
class Bar
{
public static void DoSomethingWithoutAnObjectInstance()
{
Console.WriteLine("bar");
}
struct Static : IStaticFunctionality
{
void DoSomethingWithoutAnObjectInstance() => Bar.DoSomethingWithoutAnObjectInstance();
}
}
So then a call-site for AGenericMethodThatDoesntHaveAnInstanceOfT<Foo> would actually look like:
AGenericMethodThatDoesntHaveAnInstanceOfT<Foo.Static>();

C#, implement 'static abstract' like methods

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.

Categories