请考虑以下代码示例:
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)