How to use generics with overloading? - c#

Edit: C# 3.0, net 3.5.
I am C++ programmer, so maybe I miss some simple solution in C#.
Simplified example:
I have several classes inherited from class MyBase (with method Inc). The inherited classes may override Inc. I have several overloaded "functions" (static methods) for the inherited classes:
void Print(MyInherited1 i1) ....
void Print(MyInherited2 i2) ....
and so on. Edit: those methods are "external" to the MyBase and MyInherited, they are not part of any of those classes.
I have generics function that modify its argument and call the Print function:
void Transform<T>(T t)
{
t.Inc();
Print(t);
}
Edit: this is simplified example, in real code I cannot convert the Transform method to non-generic one using just polymorphism.
Now, in C++ it would work just like that. However in C# method Inc is unknown. So I specify that T is of type MyBase.
void Transform<T>(T t) where T : MyBase
{
t.Inc();
Print(t);
}
but I still have the problem with Print -- there is no such method for the base class.
As a workaround I used ugly (!) solution -- PrintProxy where I put several
if (t is Inherited1)
Print(t as Inherited1);
else if ...
How to mix those two concepts -- overloading and generics? Nice, C# way?
Thank you in advance for help.

One option in C# 4 is to use dynamic typing:
void Transform<T>(T t)
{
t.Inc();
dynamic d = t;
Print(d);
}
That will perform the overload resolution for you at execution time - which is basically the best you can do unless you can provide a genuinely generic Print method, as there will only be one version of Transform generated.
Note that there's no real need to be generic at this point - you could replace it with:
void Transform(MyBase t)
{
...
}
I typically find that constraints based on interfaces are more useful than those based on classes, unless I'm also doing something else generic (such as creating a List<T> which should be of the right actual type).
Obviously this dynamic approach has downsides:
It requires .NET 4.0
It's slower than a compile-time binding (although it's unlikely to be significant unless you're calling it a heck of a lot)
There's no compile-time validation (you can add an overload which takes object as a sort of fallback to provide custom error handling, but you still have to wait until execution time)
Basically this is just a difference between .NET generics and C++ templating - they're very different creatures, even if they tackle many similar problems.
Rather than having static Print methods, is there any reason you can't write an abstract Print method in MyBase, and override it in each class? That feels like a more OO solution anyway, to be honest - although obviously it doesn't make sense if the printing is actually somewhat logically distant from the class itself. Even if you don't want the actual Print method in the original type hierarchy, might you be able to expose enough functionality to let you write a virtual Print method? I assume all these methods should come up with some similar kind of result, after all.
EDIT: A couple of alternative ideas...
Passing in the printer
You can pass in a delegate to do the printing. If you're calling this from a non-generic context which knows the actual type, you can take advantage of method group conversions to make this simple. Here's a short but complete example:
using System;
class Test
{
static void SampleMethod<T>(T item, Action<T> printer)
{
// You'd do all your normal stuff here
printer(item);
}
static void Print(string x)
{
Console.WriteLine("Here's a string: {0}", x);
}
static void Print(int x)
{
Console.WriteLine("Here's an integer: {0}", x);
}
static void Main()
{
SampleMethod(5, Print);
SampleMethod("hello", Print);
}
}
Use a type/delegate dictionary
Another option is to have a Dictionary<Type, Delegate> containing the printing methods. This could either be inlined (if the printing methods are simple) or something like this:
static readonly Dictionary<Type, Delegate> Printers =
new Dictionary<Type, Delegate>
{
{ typeof(MyClass1), (Action<MyClass1>) Print },
{ typeof(MyClass2), (Action<MyClass2>) Print },
{ typeof(MyClass3), (Action<MyClass3>) Print },
};
Then in your method:
Delegate printer;
if (Printers.TryGetValue(typeof(T), out printer))
{
((Action<T>) printer)(t);
}
else
{
// Error handling
}
This is another execution time solution though, and you'd need a bit more work if you wanted it to handle further derivation (e.g. walking up through the base classes if it can't find the relevant printer).

That's by design. The compiler has to know at compile time what method (overload) to bind to for the unbound (!) generic class, and in your case, this would only be known after the generic type has been set.
In contrast to the C++ templates, generics are working in a different way even though they share a similar syntax.

My first suggestion would be to use an interface instead of generics. I see no point in using generics in this example.
void Transform(IMyBase t)
{
t.Inc();
}
where IMyBase is:
interface IMyBase
{
void Inc();
}
Option A
[Edit] Since Print does not belong to IMyBase, you could separate the printing logic completely and do something like this:
void Transform(IMyBase t, IPrintLogic printLogic)
{
t.Inc();
printLogic.Print(t);
}
where IPrintLogic is defined as:
interface IPrintLogic
{
void Print(IMyBase t);
}
now you have the freedom to instantiate any print logic you want:
MyInherited1 obj = new MyInherited1();
MyPrintLogic printer = new MyPrintLogic();
Transform(obj, printer);
or, use a factory of some sort:
Transform(obj, PrintLogicFactory.Create(obj));
Code inside your factory could then be similar to a bunch of if/then/else blocks, like you have right now.
Option B - Creating an intermediate object (like the Adapter pattern)
Depending on what your Transform method actually does, this may be an option also:
IPrepared Transform(IMyBase t)
{
t.Inc();
return this.PrepareForPrinting(t);
}
and then print the IPrepared object, which is "prepared" for printing in a way:
interface IPrintLogic
{
void Print(IPrepared t);
}
In that case, you would use it like:
MyInherited1 obj = new MyInherited1();
IPrepared prepared = Transform(obj);
MyPrintLogic printer = new MyPrintLogic();
printer.Print(prepared);

why not using an interface?
void Transform<T>(T t) where T : MyBase, IMyPrintableClass
{
t.Inc();
t.Print();
}

What is the access modifier on the .Print(..) method in your MyBase class?
If none is specified it's private by default which would preclude derived classes from accessing it - mark it protected at least.
protected void Print(MyBase obj) {
//do stuff
}
If for some reason Print(..) isn't in the inheritance hierarchy and you're trying to use it in a composited way try public (although your description indicates this isn't the case).
public void Print(MyBase obj) { //...
Public is a good way to debug it because your code is most apt to "see" it whether from the same assembly or a different one.

Related

Parameter constraints - call method to check type in constraint?

I have a method with a generic parameter:
internal void DoSomething<T>(T workWithThis)
{
}
I now want to constrain this method to only accept parameters which inherit one of a few interfaces I'd like to specify. However I have not yet found a way to it. What I'd like looks like this:
internal void DoSomething<T>(T workWithThis) where T : ISomething | ISomethingElse
{
}
Obviously this is not working, so I tried it with a static method to check the Type of T:
public static bool CheckType(Type t)
{
return */check here*/
}
internal void DoSomething<T>(T workWithThis) where T : CheckType(typeof(T))
{
}
Obviously this is not going to work either. The question is why? Why is the compiler preventing me from doing that, based on my understanding there is no reason for it not to work
Why is the compiler preventing me from doing that, based on my understanding there is no reason for it not to work
The compiler is preventing you from doing it because you're trying to do something which isn't supported by C# as a language. The syntax you're trying to use does not comply with the productions in section 10.1.5 of the C# spec.
C# as a language simply does not support the scenario you require.
Now as for why the language doesn't allow this sort of flexibility - that comes down to the normal balancing act of:
How many developers would benefit from this and how much
Extra burden on other developers to understand a more complicated language
Resources (primarily within Microsoft) required to design the language feature, implement and test it
Oh, and of course this isn't just C# - the CLR would have to support such a restriction as well, and it would at least encourage other CLR languages to understand it too.
I suggest you solve this by having two separate methods. Note that they can't just be overloads of generic methods, as overloads cannot differ only by generic type constraints. If you don't mind about boxing for value types implementing the interface, you could overload with:
internal void DoSomething(ISomething something)
{
}
internal void DoSomething(ISomethingElse somethingElse)
{
}
... although then if you pass in a value where the expression is a type implementing both interfaces, you'll end up with overload ambiguity.
Alternatively, just give the two methods different names.
The compiler has to verify all the constraints at compile time, and cannot call a method to do so.
The only things you can specify in the where constraints are:
new() - require a parameterless constructor
class - must be a reference type
struct - must be a value type
SomeBaseClass
ISomeInterface
T : U - must be, inherit from, or implement one of the other generic parameters
See the C# Programming Guide - Constraints on Type Parameters for more information.
As for why, you should never have to answer "I see no reason for this to work". You have to start in the opposite direction, "Why should this work", and then come up with enough plausible and realistic scenarios and requirements to make it worthwhile to implement. See Minus 100 Points by Eric Gunnerson.
To fix this in your code, you should derive both interfaces from a common interface, and add a constraint on that instead.
If the two interfaces have nothing in common, then I question the benefit of actually adding a constraint in the first place.
For instance, if your code is going to call a method on the objects being used with the generic type/method, then obviously both interfaces have to have the same notion about what that method is, and the only way to do that would be for the method to be defined in a common base interface. That the two interfaces happen to have the same method or property declared, with the same signature, does not make it the same method.
Having said that, are you sure you even need generics here?
How about just declaring two methods, each taking one such interface?
internal void DoSomething(ISomething workWithThis)
internal void DoSomething(ISomethingElse workWithThis)
The compiler uses the generic constraint to determine what operations is available on T within the generic method - so allowing an or expression would not be type safe. For example you have two interfaces IFirst and ISecond:
public interface IFirst
{
void First();
}
public interface ISecond
{
void Second();
}
internal void DoSomething<T>(T workWithThis) where T : IFirst or ISecond
{
//How to call this method if the type is ISecond
workWithThis.First();
//How to call this method if the type is IFirst
workWithThis.Second();
}
You can define an empty interface that holds all of them.
Remember, that in C# interfaces can have multiple inheritance.
For example:
public interface IHolder : ISomething, ISomethingElse
{
}
and for generic
internal void DoSomething<T>(T workWithThis) where T : IHolder
{
}

void in C# generics?

I have a generic method that takes a request and provides a response.
public Tres DoSomething<Tres, Treq>(Tres response, Treq request)
{/*stuff*/}
But I don't always want a response for my request, and I don't always want to feed request data to get a response. I also don't want to have to copy and paste methods in their entirety to make minor changes. What I want, is to be able to do this:
public Tre DoSomething<Tres>(Tres response)
{
return DoSomething<Tres, void>(response, null);
}
Is this feasible in some manner? It seems that specifically using void doesn't work, but I'm hoping to find something analogous.
You cannot use void, but you can use object: it is a little inconvenience because your would-be-void functions need to return null, but if it unifies your code, it should be a small price to pay.
This inability to use void as a return type is at least partially responsible for a split between the Func<...> and Action<...> families of generic delegates: had it been possible to return void, all Action<X,Y,Z> would become simply Func<X,Y,Z,void>. Unfortunately, this is not possible.
No, unfortunately not. If void were a "real" type (like unit in F#, for example) life would be a lot simpler in many ways. In particular, we wouldn't need both the Func<T> and Action<T> families - there'd just be Func<void> instead of Action, Func<T, void> instead of Action<T> etc.
It would also make async simpler - there'd be no need for the non-generic Task type at all - we'd just have Task<void>.
Unfortunately, that's not the way the C# or .NET type systems work...
Here is what you can do. As #JohnSkeet said there is no unit type in C#, so make it yourself!
public sealed class ThankYou {
private ThankYou() { }
private readonly static ThankYou bye = new ThankYou();
public static ThankYou Bye { get { return bye; } }
}
Now you can always use Func<..., ThankYou> instead of Action<...>
public ThankYou MethodWithNoResult() {
/* do things */
return ThankYou.Bye;
}
Or use something already made by the Rx team: http://msdn.microsoft.com/en-us/library/system.reactive.unit%28v=VS.103%29.aspx
You could simply use Object as others have suggested. Or Int32 which I have seen some use. Using Int32 introduces a "dummy" number (use 0), but at least you can't put any big and exotic object into an Int32 reference (structs are sealed).
You could also write you own "void" type:
public sealed class MyVoid
{
MyVoid()
{
throw new InvalidOperationException("Don't instantiate MyVoid.");
}
}
MyVoid references are allowed (it's not a static class) but can only be null. The instance constructor is private (and if someone tries to call this private constructor through reflection, an exception will be thrown at them).
Since value tuples were introduced (2017, .NET 4.7), it is maybe natural to use the struct ValueTuple (the 0-tuple, the non-generic variant) instead of such a MyVoid. Its instance has a ToString() that returns "()", so it looks like a zero-tuple. As of the current version of C#, you cannot use the tokens () in code to get an instance. You can use default(ValueTuple) or just default (when the type can be inferred from the context) instead.
I like the idea by Aleksey Bykov above, but it could be simplified a bit
public sealed class Nothing {
public static Nothing AtAll { get { return null; } }
}
As I see no apparent reason why Nothing.AtAll could not just give null
The same idea (or the one by Jeppe Stig Nielsen) is also great for usage with typed classes.
E.g. if the type is only used to describe the arguments to a procedure/function passed as an argument to some method, and it itself does not take any arguments.
(You will still need to either make a dummy wrapper or to allow an optional "Nothing". But IMHO the class usage looks nice with myClass<Nothing> )
void myProcWithNoArguments(Nothing Dummy){
myProcWithNoArguments(){
}
or
void myProcWithNoArguments(Nothing Dummy=null){
...
}
void, though a type, is only valid as a return type of a method.
There is no way around this limitation of void.
What I currently do is create custom sealed types with private constructor. This is better than throwing exceptions in the c-tor because you don't have to get until runtime to figure out the situation is incorrect. It is subtly better than returning a static instance because you don't have to allocate even once. It is subtly better than returning static null because it is less verbose on the call side. The only thing the caller can do is give null.
public sealed class Void {
private Void() { }
}
public sealed class None {
private None() { }
}

Why is it impossible to declare extension methods in a generic static class?

I'd like to create a lot of extension methods for some generic class, e.g. for
public class SimpleLinkedList<T> where T:IComparable
And I've started creating methods like this:
public static class LinkedListExtensions
{
public static T[] ToArray<T>(this SimpleLinkedList<T> simpleLinkedList) where T:IComparable
{
//// code
}
}
But when I tried to make LinkedListExtensions class generic like this:
public static class LinkedListExtensions<T> where T:IComparable
{
public static T[] ToArray(this SimpleLinkedList<T> simpleLinkedList)
{
////code
}
}
I get "Extension methods can only be declared in non-generic, non-nested static class".
And I'm trying to guess where this restriction came from and have no ideas.
EDIT: Still don't have clear vision of the problem. It seems like this was just not implemented for some reason.
Generally speaking, since you do not specify the class when you use an extension method, the compiler would have no way to know which is the class where the extension method is defined:
static class GenStatic<T>
{
static void ExtMeth(this Class c) {/*...*/}
}
Class c = new Class();
c.ExtMeth(); // Equivalent to GenStatic<T>.ExtMeth(c); what is T?
Since extension methods themselves can be generic, this is no real problem at all:
static class NonGenStatic
{
static void GenExtMeth<T>(this Class c) {/*...*/}
}
Class c = newClass();
c.ExtMeth<Class2>(); // Equivalent to NonGenStatic.ExtMeth<Class2>(c); OK
You can easily rewrite your example so that the static class is not generic, but the generic methods are. In fact, this is how .NET classes such as Enumerable are written.
public static class LinkedListExtensions
{
public static T[] ToArray<T>(this SimpleLinkedList<T> where T:IComparable simpleLinkedList)
{
// code
}
}
The problem is how does the compiler do the extension resolution?
Say you define both the methods you describe:
public static class LinkedListExtensions {
public static T[] ToArray<T>(this SimpleLinkedList<T> simpleLinkedList) where T:IComparable {
//// code
}
}
public static class LinkedListExtensions<T> where T:IComparable {
public static T[] ToArray(this SimpleLinkedList<T> simpleLinkedList) {
////code
}
}
Which method is used in the following case?
SimpleLinkedList<int> data = new SimpleLinkedList<int>();
int[] dataArray = data.ToArray();
My guess is that the language designers decided to restrict extension methods to the non-generic types to avoid this scenario.
A very interesting question, I have never been tempted to use static generic classes, but at least it seems possible.
In the context of declaring extension methods, you cannot only declare extension methods for a certain generic type (such as IEnumerable<T>) but also bring the type parameter T into the equation. If we agree to treat IEnumerable<int> and IEnumerable<string> as different types, this makes sense on a conceptual level too.
Being able to declare your extension methods in a static generic class would save you repeating your type parameter constraints over and over again, in effect grouping all extension methods for IEnumerable<T> where T : IComparable together.
According to the specification (citation needed), extension methods can only be declared in static not-nested and not-generic classes. The reason for the first two constraints are fairly obvious:
May not carry any state as it's not a mixin, just syntactic sugar.
Must have the same lexical scope as the type it provides extensions for.
The restriction on non-generic static classes seems a little arbitrary to me, I can't come up with a technical reason here. But it might be that the language designers decided to discourage you in writing extension methods that depend on the type parameter of a generic class you wish to provide extension methods for. Instead they want you to provide a truly generic implementation of your extension method but make it possible to provide optimized/specialized (compile-time bound) versions of your extension methods in addition to your general implementation.
Reminds me of template specialization in C++. EDIT: Unfortunately this is wrong, please see my additions below.
Ok, as this is a really interesting topic I did some further research. There actually is a technical restriction that I missed here. Let's look at some code:
public static class Test
{
public static void DoSomething<T>(this IEnumerable<T> source)
{
Console.WriteLine("general");
}
public static void DoSomething<T>(this IEnumerable<T> source) where T :IMyInterface
{
Console.WriteLine("specific");
}
}
This will actually fail with this compiler error:
Type 'ConsoleApplication1.Test'
already defines a member called
'DoSomething' with the same parameter
types
Ok, next we try splitting it up into two different extensions classes:
public interface IMyInterface { }
public class SomeType : IMyInterface {}
public static class TestSpecific
{
public static void DoSomething<T>(this IEnumerable<T> source) where T : IMyInterface
{
Console.WriteLine("specific");
}
}
public static class TestGeneral
{
public static void DoSomething<T>(this IEnumerable<T> source)
{
Console.WriteLine("general");
}
}
class Program
{
static void Main(string[] args)
{
var general = new List<int>();
var specific = new List<SomeType>();
general.DoSomething();
specific.DoSomething();
Console.ReadLine();
}
}
Against my initial impression (it was late yesterday night), this will result in an ambiguity at the call sites. To resolve this ambiguity one would need to call the extension method in a traditional way, but that's against our intention.
So this leaves us with a situation where it's not possible to declare compile-time bound generic specializations of extension methods. On the other hand, there is still no reason why we couldn't declare extension methods only for a single special generic type parameter. Therefore it'd be nice to declare them in a static generic class.
On the other hand writing an extension method like:
public static void DoSomething<T>(this IEnumerable<T> source) where T : IMyInterface {}
or
public static void DoSomething(this IEnumerable<IMyInterface> source) {}
is not all too different and only requires a little casting on the call site vs. on the extension method side (you will probably implement some optimization that depends on the specific type, so you'd need to cast T to IMyInterface or whatever anyway). So the only reason I can come up with is again, the language designers want to encourage you in writing generic extensions only in a truly generic fashion.
Some interesting things could happen here if we take co/contravariance in to the equation, which are about to be introduced with C# 4.0.
Don't think of extension methods as being tied to the static class in which they are contained. Instead, think of them as being tied to a specific namespace. Therefore, the static class in which they are defined is simply a shell used to declare these methods within the namespace. And while you could very well write multiple classes for different types of extension methods, you shouldn't think of the class itself as anything more than a way to clearly group your extension methods.
Extension methods do not extend any attributes of the class in which they are contained. The signature of the method will define everything about the extension method. And while you could also call your method like this, LinkedListExtensions.ToArray(...), I do not believe that was the intent for extension methods. As such, I believe the framework creators probably created the restriction you ran into as a way to inform developers simply that extension methods are self-contained and are not directly tied to the class in which they reside.
Just a thought, but is there any reason you can't just derive from this class and add the extra methods to the specialization rather than writing a suite of extension methods? I am sure you have your reasons but just throwing that out there.
Static classes should be able to be defined as abstract. If they were able to do this, then you could specify that they could not be used directly, but must be inherited just like a regular class and then generic static classes would be doable for extension methods because you could define them in the abstract class, inherit from said class, and everything would work properly.
As it is right now, there are a ton of significant limitations with static classes, this just being one that really messes with the mojo in a lot of cases. Combined with the inability to have the compiler infer the return type and thus requiring you to enter the whole generic implementation to call generic functions that don't have all of the generics in the method signature makes this stuff aggravatingly weak and makes for a lot of typing that shouldn't need to be there.
(There is also the case where the second generic is defined in the definition of the first and it won't use it, even though it's obvious to infer as well at compile time. This one is super annoying because it is completely obvious.) MS has a TON of work on Generics that they could be doing to improve this stuff.

Polymorphic or generic approach is better? C#

I have two classes and an interface like
interface IVehicle
{
void Drive();
}
class Benz :IVehicle
{
public void Drive()
{
Console.WriteLine("WOW! driving benz");
}
}
class Ferrari : IVehicle
{
public void Drive()
{
Console.WriteLine("WOW! driving ferrari");
}
}
I got a Driver class which uses this.
class Driver
{
public void StartDriving(IVehicle vehicle)
{
vehicle.Drive();
}
}
There is one more driver which is generic.
class GenericDriver
{
public void StartDriving<T>() where T : IVehicle , new()
{
T vehicle = new T();
vehicle.Drive();
}
}
Questions
Do you see any advantages for the generic implementation compared to normal Driver? If yes, what are they?
Which one do you prefer? A generic one or the normal one?
Is there a better way to implement a generic driver?
I am getting a feeling that generics in C# is very limited when compared with C++ templates. Is that true?
Any thoughts?
Absolutely no advantages in this case whatsoever. Except if you really want to create an instance of T in Drive(), which can be done without generics with delegate IVehicle VehicleBuilder();
It depends on the situation. But generally speaking I'd prefer first.
Again: it depends on what you want to do.
Yes, this is true. Remember though, that C++ templates are compile-time (JIT time) constructs, whereas C# generics are run-time constructs.
Now on why would I want a generic Driver. Consider:
class Driver<TVehicle>
where TVehicle : class, IVehicle, new()
{
public TVehicle Vehicle { get; set }
public Driver()
{
Vehicle = new TVehicle();
}
}
This way I'll be able to use a strongly-typed Driver<>.Vehicle property which will be of a particular type, rather than of a more common IVehicle.
I don't really see any advantages in your example, but they do different things. The normal one has the ability to use an already created vehicle, while the generic one can only create a new one.
Since these methods do different things, it depends. Whichever works better for your code. Personally I would use the normal one.
I'm not really sure why you even want to use generics. It doesn't help you much in this case.
Yes, C++ templates are much more powerful. Just look at all the weird Boost libraries. This is mainly because C++ templates are done at compile time, not run time/JIT time like in .NET.
The second means you need to construct a new object every time it is called, whereas the first would allow you to construct outside of the call and hence reuse the object, which could save a lot on resources if called often.

Why Doesn't C# Allow Static Methods to Implement an Interface?

Why was C# designed this way?
As I understand it, an interface only describes behaviour, and serves the purpose of describing a contractual obligation for classes implementing the interface that certain behaviour is implemented.
If classes wish to implement that behavour in a shared method, why shouldn't they?
Here is an example of what I have in mind:
// These items will be displayed in a list on the screen.
public interface IListItem {
string ScreenName();
...
}
public class Animal: IListItem {
// All animals will be called "Animal".
public static string ScreenName() {
return "Animal";
}
....
}
public class Person: IListItem {
private string name;
// All persons will be called by their individual names.
public string ScreenName() {
return name;
}
....
}
Assuming you are asking why you can't do this:
public interface IFoo {
void Bar();
}
public class Foo: IFoo {
public static void Bar() {}
}
This doesn't make sense to me, semantically. Methods specified on an interface should be there to specify the contract for interacting with an object. Static methods do not allow you to interact with an object - if you find yourself in the position where your implementation could be made static, you may need to ask yourself if that method really belongs in the interface.
To implement your example, I would give Animal a const property, which would still allow it to be accessed from a static context, and return that value in the implementation.
public class Animal: IListItem {
/* Can be tough to come up with a different, yet meaningful name!
* A different casing convention, like Java has, would help here.
*/
public const string AnimalScreenName = "Animal";
public string ScreenName(){ return AnimalScreenName; }
}
For a more complicated situation, you could always declare another static method and delegate to that. In trying come up with an example, I couldn't think of any reason you would do something non-trivial in both a static and instance context, so I'll spare you a FooBar blob, and take it as an indication that it might not be a good idea.
My (simplified) technical reason is that static methods are not in the vtable, and the call site is chosen at compile time. It's the same reason you can't have override or virtual static members. For more details, you'd need a CS grad or compiler wonk - of which I'm neither.
For the political reason, I'll quote Eric Lippert (who is a compiler wonk, and holds a Bachelor of Mathematics, Computer science and Applied Mathematics from University of Waterloo (source: LinkedIn):
...the core design principle of static methods, the principle that gives them their name...[is]...it can always be determined exactly, at compile time, what method will be called. That is, the method can be resolved solely by static analysis of the code.
Note that Lippert does leave room for a so-called type method:
That is, a method associated with a type (like a static), which does not take a non-nullable “this” argument (unlike an instance or virtual), but one where the method called would depend on the constructed type of T (unlike a static, which must be determinable at compile time).
but is yet to be convinced of its usefulness.
Most answers here seem to miss the whole point. Polymorphism can be used not only between instances, but also between types. This is often needed, when we use generics.
Suppose we have type parameter in generic method and we need to do some operation with it. We dont want to instantinate, because we are unaware of the constructors.
For example:
Repository GetRepository<T>()
{
//need to call T.IsQueryable, but can't!!!
//need to call T.RowCount
//need to call T.DoSomeStaticMath(int param)
}
...
var r = GetRepository<Customer>()
Unfortunately, I can come up only with "ugly" alternatives:
Use reflection
Ugly and beats the idea of interfaces and polymorphism.
Create completely separate factory class
This might greatly increase the complexity of the code. For example, if we are trying to model domain objects, each object would need another repository class.
Instantiate and then call the desired interface method
This can be hard to implement even if we control the source for the classes, used as generic parameters. The reason is that, for example we might need the instances to be only in well-known, "connected to DB" state.
Example:
public class Customer
{
//create new customer
public Customer(Transaction t) { ... }
//open existing customer
public Customer(Transaction t, int id) { ... }
void SomeOtherMethod()
{
//do work...
}
}
in order to use instantination for solving the static interface problem we need to do the following thing:
public class Customer: IDoSomeStaticMath
{
//create new customer
public Customer(Transaction t) { ... }
//open existing customer
public Customer(Transaction t, int id) { ... }
//dummy instance
public Customer() { IsDummy = true; }
int DoSomeStaticMath(int a) { }
void SomeOtherMethod()
{
if(!IsDummy)
{
//do work...
}
}
}
This is obviously ugly and also unnecessary complicates the code for all other methods. Obviously, not an elegant solution either!
I know it's an old question, but it's interesting. The example isn't the best. I think it would be much clearer if you showed a usage case:
string DoSomething<T>() where T:ISomeFunction
{
if (T.someFunction())
...
}
Merely being able to have static methods implement an interface would not achieve what you want; what would be needed would be to have static members as part of an interface. I can certainly imagine many usage cases for that, especially when it comes to being able to create things. Two approaches I could offer which might be helpful:
Create a static generic class whose type parameter will be the type you'd be passing to DoSomething above. Each variation of this class will have one or more static members holding stuff related to that type. This information could supplied either by having each class of interest call a "register information" routine, or by using Reflection to get the information when the class variation's static constructor is run. I believe the latter approach is used by things like Comparer<T>.Default().
For each class T of interest, define a class or struct which implements IGetWhateverClassInfo<T> and satisfies a "new" constraint. The class won't actually contain any fields, but will have a static property which returns a static field with the type information. Pass the type of that class or struct to the generic routine in question, which will be able to create an instance and use it to get information about the other class. If you use a class for this purpose, you should probably define a static generic class as indicated above, to avoid having to construct a new descriptor-object instance each time. If you use a struct, instantiation cost should be nil, but every different struct type would require a different expansion of the DoSomething routine.
None of these approaches is really appealing. On the other hand, I would expect that if the mechanisms existed in CLR to provide this sort of functionality cleanly, .net would allow one to specify parameterized "new" constraints (since knowing if a class has a constructor with a particular signature would seem to be comparable in difficulty to knowing if it has a static method with a particular signature).
Short-sightedness, I'd guess.
When originally designed, interfaces were intended only to be used with instances of class
IMyInterface val = GetObjectImplementingIMyInterface();
val.SomeThingDefinedinInterface();
It was only with the introduction of interfaces as constraints for generics did adding a static method to an interface have a practical use.
(responding to comment:) I believe changing it now would require a change to the CLR, which would lead to incompatibilities with existing assemblies.
To the extent that interfaces represent "contracts", it seems quiet reasonable for static classes to implement interfaces.
The above arguments all seem to miss this point about contracts.
Interfaces specify behavior of an object.
Static methods do not specify a behavior of an object, but behavior that affects an object in some way.
Because the purpose of an interface is to allow polymorphism, being able to pass an instance of any number of defined classes that have all been defined to implement the defined interface... guaranteeing that within your polymorphic call, the code will be able to find the method you are calling. it makes no sense to allow a static method to implement the interface,
How would you call it??
public interface MyInterface { void MyMethod(); }
public class MyClass: MyInterface
{
public static void MyMethod() { //Do Something; }
}
// inside of some other class ...
// How would you call the method on the interface ???
MyClass.MyMethod(); // this calls the method normally
// not through the interface...
// This next fails you can't cast a classname to a different type...
// Only instances can be Cast to a different type...
MyInterface myItf = MyClass as MyInterface;
Actually, it does.
As of Mid-2022, the current version of C# has full support for so-called static abstract members:
interface INumber<T>
{
static abstract T Zero { get; }
}
struct Fraction : INumber<Fraction>
{
public static Fraction Zero { get; } = new Fraction();
public long Numerator;
public ulong Denominator;
....
}
Please note that depending on your version of Visual Studio and your installed .NET SDK, you'll either have to update at least one of them (or maybe both), or that you'll have to enable preview features (see Use preview features & preview language in Visual Studio).
See more:
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/static-virtual-interface-members
https://blog.ndepend.com/c-11-static-abstract-members/
https://khalidabuhakmeh.com/static-abstract-members-in-csharp-10-interfaces#:~:text=Static%20abstract%20members%20allow%20each,like%20any%20other%20interface%20definition.
Regarding static methods used in non-generic contexts I agree that it doesn't make much sense to allow them in interfaces, since you wouldn't be able to call them if you had a reference to the interface anyway. However there is a fundamental hole in the language design created by using interfaces NOT in a polymorphic context, but in a generic one. In this case the interface is not an interface at all but rather a constraint. Because C# has no concept of a constraint outside of an interface it is missing substantial functionality. Case in point:
T SumElements<T>(T initVal, T[] values)
{
foreach (var v in values)
{
initVal += v;
}
}
Here there is no polymorphism, the generic uses the actual type of the object and calls the += operator, but this fails since it can't say for sure that that operator exists. The simple solution is to specify it in the constraint; the simple solution is impossible because operators are static and static methods can't be in an interface and (here is the problem) constraints are represented as interfaces.
What C# needs is a real constraint type, all interfaces would also be constraints, but not all constraints would be interfaces then you could do this:
constraint CHasPlusEquals
{
static CHasPlusEquals operator + (CHasPlusEquals a, CHasPlusEquals b);
}
T SumElements<T>(T initVal, T[] values) where T : CHasPlusEquals
{
foreach (var v in values)
{
initVal += v;
}
}
There has been lots of talk already about making an IArithmetic for all numeric types to implement, but there is concern about efficiency, since a constraint is not a polymorphic construct, making a CArithmetic constraint would solve that problem.
Because interfaces are in inheritance structure, and static methods don't inherit well.
What you seem to want would allow for a static method to be called via both the Type or any instance of that type. This would at very least result in ambiguity which is not a desirable trait.
There would be endless debates about whether it mattered, which is best practice and whether there are performance issues doing it one way or another. By simply not supporting it C# saves us having to worry about it.
Its also likely that a compilier that conformed to this desire would lose some optimisations that may come with a more strict separation between instance and static methods.
You can think of the static methods and non-static methods of a class as being different interfaces. When called, static methods resolve to the singleton static class object, and non-static methods resolve to the instance of the class you deal with. So, if you use static and non-static methods in an interface, you'd effectively be declaring two interfaces when really we want interfaces to be used to access one cohesive thing.
To give an example where I am missing either static implementation of interface methods or what Mark Brackett introduced as the "so-called type method":
When reading from a database storage, we have a generic DataTable class that handles reading from a table of any structure. All table specific information is put in one class per table that also holds data for one row from the DB and which must implement an IDataRow interface. Included in the IDataRow is a description of the structure of the table to read from the database. The DataTable must ask for the datastructure from the IDataRow before reading from the DB. Currently this looks like:
interface IDataRow {
string GetDataSTructre(); // How to read data from the DB
void Read(IDBDataRow); // How to populate this datarow from DB data
}
public class DataTable<T> : List<T> where T : IDataRow {
public string GetDataStructure()
// Desired: Static or Type method:
// return (T.GetDataStructure());
// Required: Instantiate a new class:
return (new T().GetDataStructure());
}
}
The GetDataStructure is only required once for each table to read, the overhead for instantiating one more instance is minimal. However, it would be nice in this case here.
FYI: You could get a similar behavior to what you want by creating extension methods for the interface. The extension method would be a shared, non overridable static behavior. However, unfortunately, this static method would not be part of the contract.
Interfaces are abstract sets of defined available functionality.
Whether or not a method in that interface behaves as static or not is an implementation detail that should be hidden behind the interface. It would be wrong to define an interface method as static because you would be unnecessarily forcing the method to be implemented in a certain way.
If methods were defined as static, the class implementing the interface wouldn't be as encapsulated as it could be. Encapsulation is a good thing to strive for in object oriented design (I won't go into why, you can read that here: http://en.wikipedia.org/wiki/Object-oriented). For this reason, static methods aren't permitted in interfaces.
Static classes should be able to do this so they can be used generically. I had to instead implement a Singleton to achieve the desired results.
I had a bunch of Static Business Layer classes that implemented CRUD methods like "Create", "Read", "Update", "Delete" for each entity type like "User", "Team", ect.. Then I created a base control that had an abstract property for the Business Layer class that implemented the CRUD methods. This allowed me to automate the "Create", "Read", "Update", "Delete" operations from the base class. I had to use a Singleton because of the Static limitation.
Most people seem to forget that in OOP Classes are objects too, and so they have messages, which for some reason c# calls "static method".
The fact that differences exist between instance objects and class objects only shows flaws or shortcomings in the language.
Optimist about c# though...
OK here is an example of needing a 'type method'. I am creating one of a set of classes based on some source XML. So I have a
static public bool IsHandled(XElement xml)
function which is called in turn on each class.
The function should be static as otherwise we waste time creating inappropriate objects.
As #Ian Boyde points out it could be done in a factory class, but this just adds complexity.
It would be nice to add it to the interface to force class implementors to implement it. This would not cause significant overhead - it is only a compile/link time check and does not affect the vtable.
However, it would also be a fairly minor improvement. As the method is static, I as the caller, must call it explicitly and so get an immediate compile error if it is not implemented. Allowing it to be specified on the interface would mean this error comes marginally earlier in the development cycle, but this is trivial compared to other broken-interface issues.
So it is a minor potential feature which on balance is probably best left out.
The fact that a static class is implemented in C# by Microsoft creating a special instance of a class with the static elements is just an oddity of how static functionality is achieved. It is isn't a theoretical point.
An interface SHOULD be a descriptor of the class interface - or how it is interacted with, and that should include interactions that are static. The general definition of interface (from Meriam-Webster): the place or area at which different things meet and communicate with or affect each other. When you omit static components of a class or static classes entirely, we are ignoring large sections of how these bad boys interact.
Here is a very clear example of where being able to use interfaces with static classes would be quite useful:
public interface ICrudModel<T, Tk>
{
Boolean Create(T obj);
T Retrieve(Tk key);
Boolean Update(T obj);
Boolean Delete(T obj);
}
Currently, I write the static classes that contain these methods without any kind of checking to make sure that I haven't forgotten anything. Is like the bad old days of programming before OOP.
C# and the CLR should support static methods in interfaces as Java does. The static modifier is part of a contract definition and does have meaning, specifically that the behavior and return value do not vary base on instance although it may still vary from call to call.
That said, I recommend that when you want to use a static method in an interface and cannot, use an annotation instead. You will get the functionality you are looking for.
Static Methods within an Interface are allowed as of c# 9 (see https://www.dotnetcurry.com/csharp/simpler-code-with-csharp-9).
I think the short answer is "because it is of zero usefulness".
To call an interface method, you need an instance of the type. From instance methods you can call any static methods you want to.
I think the question is getting at the fact that C# needs another keyword, for precisely this sort of situation. You want a method whose return value depends only on the type on which it is called. You can't call it "static" if said type is unknown. But once the type becomes known, it will become static. "Unresolved static" is the idea -- it's not static yet, but once we know the receiving type, it will be. This is a perfectly good concept, which is why programmers keep asking for it. But it didn't quite fit into the way the designers thought about the language.
Since it's not available, I have taken to using non-static methods in the way shown below. Not exactly ideal, but I can't see any approach that makes more sense, at least not for me.
public interface IZeroWrapper<TNumber> {
TNumber Zero {get;}
}
public class DoubleWrapper: IZeroWrapper<double> {
public double Zero { get { return 0; } }
}
As per Object oriented concept Interface implemented by classes and
have contract to access these implemented function(or methods) using
object.
So if you want to access Interface Contract methods you have to create object. It is always must that is not allowed in case of Static methods. Static classes ,method and variables never require objects and load in memory without creating object of that area(or class) or you can say do not require Object Creation.
Conceptually there is no reason why an interface could not define a contract that includes static methods.
For the current C# language implementation, the restriction is due to the allowance of inheritance of a base class and interfaces. If "class SomeBaseClass" implements "interface ISomeInterface" and "class SomeDerivedClass : SomeBaseClass, ISomeInterface" also implements the interface, a static method to implement an interface method would fail compile because a static method cannot have same signature as an instance method (which would be present in base class to implement the interface).
A static class is functionally identical to a singleton and serves the same purpose as a singleton with cleaner syntax. Since a singleton can implement an interface, interface implementations by statics are conceptually valid.
So it simply boils down to the limitation of C# name conflict for instance and static methods of the same name across inheritance. There is no reason why C# could not be "upgraded" to support static method contracts (interfaces).
An interface is an OOPS concept, which means every member of the interface should get used through an object or instance. Hence, an interface can not have static methods.
When a class implements an interface,it is creating instance for the interface members. While a static type doesnt have an instance,there is no point in having static signatures in an interface.

Categories

Resources