1

I have the following implementation which uses .NET 7's static abstract member functionality:

public interface IFoo
{
    public static abstract string Bar { get; }
}

public class Foo : IFoo
{
    public static string Bar => "Bar"
}

Now, whenever I use the interface as a type parameter to a generic class, I get an error. For example, if my Program.cs looks like this:

List<IFoo> fooList = new List<Foo>();

I get the following error:

error CS8920: The interface 'IFoo' cannot be used as type argument. Static member 'IFoo.Bar' does not have a most specific implementation in the interface.

I guess that, for whatever reason, this is a C# restriction. I could be wrong, though, so now I'm asking: is there any way to solve this case or at least get around this restriction?

Andreas Forslöw
  • 2,220
  • 23
  • 32

1 Answers1

1

I guess that, for whatever reason, this is a C# restriction.

Yes, the restriction is explained in the specification and the reason is type safety. Example from the linked github issue:

interface I
{
    static abstract string P { get; }
}
class C<T> where T : I
{
    void M() { Console.WriteLine(T.P); }
}
new C<I>().M(); // Error

You can "fix" it by using the static virtual method:

public interface IFoo
{
    public static virtual string Bar => throw new Exception();
}

Problem here is that now implementors do not need to implement the method:

public class Foo1 : IFoo // valid now
{
}

Another approach is to use marker interface (though it can be considered an antipattern):

public interface IAmActuallyFoo
{
    
}
public interface IFoo : IAmActuallyFoo
{
    public static abstract string Bar { get; }
}

var fooList = new List<IAmActuallyFoo>();

P.S.

Note that List<IFoo> fooList = new List<Foo>(); is invalid anyway because variance is not supported by classes (see docs, this and/or this answer).

Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • Nice! Even though it could break things, it's a bit weird to me that you can't use the interface as a type parameter, since that is a very common scenario. The use case I currently have for this is polymorphic deserialization of json. That basically requires that the type argument is the interface. Good thing that the virtual method exists, but it's a shame that you can't enforce the implementation. Anyways, thanks! – Andreas Forslöw Mar 09 '23 at 15:52
  • @AndreasForslöw was glad to help! If you really want - you can enforce the implementation by writing custom analyzer =) – Guru Stron Mar 09 '23 at 15:56
  • Right... I didn't even think about the invalid syntax. Anyways, I hope it's clear to everyone that the question is just a very simple mockup to demonstrate the issue. And yeah, a custom analyzer is definitely a smart option.. Just a very ambitious one :) – Andreas Forslöw Mar 09 '23 at 16:02