请考虑以下代码示例:
public interface IPlayer
{
int Attack(int amount);
}
public interface IPowerPlayer: IPlayer
{
int IPlayer.Attack(int amount)
{
return amount + 50;
}
}
public interface ILimitedPlayer: IPlayer
{
new int Attack(int amount)
{
return amount + 10;
}
}
public class Player : IPowerPlayer, ILimitedPlayer
{
}
Run Code Online (Sandbox Code Playgroud)
我的问题在于代码:
IPlayer player = new Player();
Console.WriteLine(player.Attack(5)); // Output 55, --> im not sure from this output. I can compile the code but not execute it!
IPowerPlayer powerPlayer = new Player();
Console.WriteLine(powerPlayer.Attack(5)); …
Run Code Online (Sandbox Code Playgroud) 考虑带有委托的逆变接口定义:
public interface IInterface<in TInput>
{
delegate int Foo(int x);
void Bar(TInput input);
void Baz(TInput input, Foo foo);
}
Run Code Online (Sandbox Code Playgroud)
Baz
失败的定义出现错误:
CS1961
无效方差:类型参数“TInput
”必须在“IInterface<TInput>.Baz(TInput, IInterface<TInput>.Foo)
”上协变有效。'TInput
' 是逆变的。
我的问题是为什么?乍一看,这应该是有效的,因为Foo
委托与TInput
. 我不知道是编译器过于保守还是我遗漏了什么。
请注意,通常您不会在接口内声明委托,特别是这不会在早于 C# 8 的版本上编译,因为接口中的委托需要默认接口实现。
如果允许这个定义,有没有办法打破类型系统,或者编译器是否保守?
c# generics covariance contravariance default-interface-member
使用C#-8.0的.Net Core Console应用程序中以下界面没有错误
interface I
{
public abstract void f();
public virtual void g() => Console.WriteLine("g");
public sealed void h() => Console.WriteLine("h");
}
Run Code Online (Sandbox Code Playgroud)
abstract
防止在接口中添加定义。virtual
并且sealed
需要在接口中进行定义。sealed
阻止派生类中的实现h
。
abstract
在接口中使用、virtual
和 sealed
时,在当前实现的 C# - 8 版本中还有其他含义或应用吗?它们应该如何以及何时在界面中使用?
我最近遇到了要考虑在下一版本的C#中添加的功能列表。其中之一称为“默认接口方法”:
https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md
简而言之,它将允许您在接口本身上定义实际的方法实现,这意味着接口现在可以具有实现。既然是这种情况,并且C#类可以从多个接口实现/继承,那么为什么我在世界上总是使用抽象类?
我唯一想到的是接口不能具有构造函数,因此可能需要在抽象类构造函数中运行一些逻辑,这将有理由定义一个抽象类。
还有其他人能想到的方案吗?
C#8支持接口中的默认方法实现。我的想法是将一个日志记录方法注入这样的类中:
public interface ILoggable {
void Log(string message) => DoSomethingWith(message);
}
public class MyClass : ILoggable {
void MyMethod() {
Log("Using injected logging"); // COMPILER ERROR
}
}
Run Code Online (Sandbox Code Playgroud)
我收到一个编译器错误:“名称在当前上下文中不存在”
以这种方式使用默认方法实现是不可能的吗?
编辑:
C# 8.0 引入了一个新的语言特性——接口成员的默认实现。
public interface IRobot
{
void Talk(string message)
{
Debug.WriteLine(message);
}
}
Run Code Online (Sandbox Code Playgroud)
新的默认接口实现提供了特性语言的元素。然而,这也模糊了抽象类和接口之间的界限。
现在使用抽象类而不是具有默认实现的接口有什么好处?
目前,关于新 C#8 默认接口实现(特征)的事件限制的文档很少。我对规范提案特别困惑。该示例不仅给出了无效的 C#(“覆盖”事件缺少标识符),而且在 C#8(VS2019、.NET Core 3.0)中实现其中任何一个都会返回大量编译器异常。此外,C#8 的发行说明没有提及任何接口特征的事件。当我继续尝试寻找答案时,我也无法从开放问题列表中收集到任何有用的信息。
那么问题来了:这个功能是否实现并可用?如果是这样,正确的语法是什么?
我按照本指南https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods来使用默认接口实现功能。我复制了一段代码,该代码在接口中定义了默认实现IA
,然后在接口中覆盖它IB
:
interface I0
{
void M() { Console.WriteLine("I0"); }
}
interface I1 : I0
{
override void M() { Console.WriteLine("I1"); }
}
Run Code Online (Sandbox Code Playgroud)
但它给出了一个错误CS0106 The modifier 'override' is not valid for this item
和一个警告CS0108 'I1.M()' hides inherited member 'I0.M()'. Use the new keyword if hiding was intended
。TargetFramework
设置为net5.0
,LangVersion
是latest
。为什么即使官方文档中描述了它也不起作用?
我在 Visual Studio 2019 中有一个 .Net 6.0 应用程序。我正在尝试让默认接口实现正常工作。由于某种原因,它似乎无法识别类定义中的默认实现。
这是一个示例代码片段:
public interface IFooBar
{
protected bool BoolProperty { get; set; }
protected Guid StringProperty { get; set; }
protected void SampleMethod1(string param)
{
}
protected void SampleMethod2()
{
}
}
public class FooBase
{
}
public class Foo : FooBase, IFooBar
{
protected bool IFooBar.BoolProperty { get; set; }
protected Guid IFooBar.StringProperty { get; set; }
protected SomeMethod()
{
SampleMethod1("Test String");
}
}
Run Code Online (Sandbox Code Playgroud)
以下是我的 Visual Studio 2019 项目文件的片段:
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework> …
Run Code Online (Sandbox Code Playgroud)