接口不能用作类型参数。接口中的静态成员没有最具体的实现。

huangapple go评论102阅读模式
英文:

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:

  1. public interface IFoo
  2. {
  3. public static abstract string Bar { get; }
  4. }
  5. public class Foo : IFoo
  6. {
  7. public static string Bar => "Bar";
  8. }

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:

  1. 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:

  1. public interface IFoo
  2. {
  3. public static abstract string Bar { get; }
  4. }
  5. public class Foo : IFoo
  6. {
  7. public static string Bar =&gt; &quot;Bar&quot;
  8. }

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:

  1. List&lt;IFoo&gt; fooList = new List&lt;Foo&gt;();

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 问题的示例:

  1. interface I
  2. {
  3. static abstract string P { get; }
  4. }
  5. class C&lt;T&gt; where T : I
  6. {
  7. void M() { Console.WriteLine(T.P); }
  8. }
  9. new C&lt;I&gt;().M(); // 错误

您可以通过使用 static virtual 方法来“修复”它:

  1. public interface IFoo
  2. {
  3. public static virtual string Bar =&gt; throw new Exception();
  4. }

这里的问题是现在实现者不需要实现这个方法:

  1. public class Foo1 : IFoo // 现在是有效的
  2. {
  3. }

另一种方法是使用标记接口(尽管它可能被视为反模式):

  1. public interface IAmActuallyFoo
  2. {
  3. }
  4. public interface IFoo : IAmActuallyFoo
  5. {
  6. public static abstract string Bar { get; }
  7. }
  8. var fooList = new List&lt;IAmActuallyFoo&gt;();

附注:

请注意,List&lt;IFoo&gt; fooList = new List&lt;Foo&gt;(); 无论如何都是无效的,因为类不支持协变性(请参见文档这个这个 答案)。

英文:

> 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:

  1. interface I
  2. {
  3. static abstract string P { get; }
  4. }
  5. class C&lt;T&gt; where T : I
  6. {
  7. void M() { Console.WriteLine(T.P); }
  8. }
  9. new C&lt;I&gt;().M(); // Error

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

  1. public interface IFoo
  2. {
  3. public static virtual string Bar =&gt; throw new Exception();
  4. }

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

  1. public class Foo1 : IFoo // valid now
  2. {
  3. }

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

  1. public interface IAmActuallyFoo
  2. {
  3. }
  4. public interface IFoo : IAmActuallyFoo
  5. {
  6. public static abstract string Bar { get; }
  7. }
  8. var fooList = new List&lt;IAmActuallyFoo&gt;();

P.S.

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

huangapple
  • 本文由 发表于 2023年3月9日 23:16:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/75686568.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定