英文:
The interface cannot be used as type argument. Static member does not have a most specific implementation in the interface
问题
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 a 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?
英文:
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?
答案1
得分: 3
> 我猜,不管出于什么原因,这是 C# 的一种限制。
是的,这个限制在规范中有解释,原因是类型安全。来自链接的 GitHub 问题的示例:
interface I
{
static abstract string P { get; }
}
class C<T> where T : I
{
void M() { Console.WriteLine(T.P); }
}
new C<I>().M(); // 错误
您可以通过使用 static virtual
方法来“修复”它:
public interface IFoo
{
public static virtual string Bar => throw new Exception();
}
这里的问题是现在实现者不需要实现这个方法:
public class Foo1 : IFoo // 现在是有效的
{
}
另一种方法是使用标记接口(尽管它可能被视为反模式):
public interface IAmActuallyFoo
{
}
public interface IFoo : IAmActuallyFoo
{
public static abstract string Bar { get; }
}
var fooList = new List<IAmActuallyFoo>();
附注:
请注意,List<IFoo> fooList = new List<Foo>();
无论如何都是无效的,因为类不支持协变性(请参见文档、这个 或这个 答案)。
英文:
> 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).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论