标签: default-interface-member

你会如何在C#中实现"特质"设计模式?

我知道这个功能在C#中不存在,但PHP最近添加了一个名为Traits的功能,我认为这个功能起初有点傻,直到我开始考虑它.

假设我有一个名为的基类Client.Client有一个叫做的属性Name.

现在我正在开发一个可供许多不同客户使用的可重用应用程序.所有客户都同意客户应该有一个名字,因此它属于基类.

现在客户A出现并表示他还需要跟踪客户的权重.客户B不需要重量,但他想跟踪高度.客户C想要跟踪重量和高度.

有了特征,我们可以制作权重和高度特征:

class ClientA extends Client use TClientWeight
class ClientB extends Client use TClientHeight
class ClientC extends Client use TClientWeight, TClientHeight
Run Code Online (Sandbox Code Playgroud)

现在,我可以满足所有客户的需求,而无需在课堂上添加任何额外的毛病.如果我的客户稍后回来并说"哦,我真的很喜欢这个功能,我也可以拥有它吗?",我只是更新了类定义以包含额外的特性.

你会如何在C#中实现这一目标?

接口在这里不起作用,因为我想要对属性和任何相关方法的具体定义,我不想为每个版本的类重新实现它们.

("客户",我指的是雇用我作为开发人员的文字人员,而"客户"我指的是编程课程;我的每个客户都有他们想要记录信息的客户)

c# code-reuse design-patterns traits default-interface-member

48
推荐指数
5
解决办法
2万
查看次数

如何在继承的函数中重新定义在主体接口中定义的函数而不覆盖?

有人可以解释同一类上的相同函数的行为有何不同吗?

using System;

public class HelloWorld
{
    public static void Main(string[] args)
    {
        MyUpperScript mAsdfScript = new MyUpperScript();
        IInterface mAsdfInterface = mAsdfScript;
        mAsdfScript.Foo();
        mAsdfInterface.Foo();
    }
}

public class MyUpperScript : MyScript
{
    public void Foo()
    {
        Console.WriteLine("Upper Script");
    }
}
public class MyScript : IInterface
{

}

public interface IInterface
{
    public void Foo()
    {
        Console.WriteLine("Interface");
    }
}

Run Code Online (Sandbox Code Playgroud)

我期望它在 Foo() 调用上都写“Upper Script”

请注意,如果我也从接口派生第二个类,它会按照我期望的方式工作 - 都打印“Upper Script”:

// now deriving for the interface too:
public class MyUpperScript : MyScript, IInterface
{ …
Run Code Online (Sandbox Code Playgroud)

c# inheritance overriding interface default-interface-member

21
推荐指数
1
解决办法
953
查看次数

C# 8.0 默认接口成员的意外行为

考虑以下代码:

interface I {
    string M1() => "I.M1";
    string M2() => "I.M2";
}

abstract class A : I {}

class C : A {
    public string M1() => "C.M1";
    public virtual string M2() => "C.M2";
}

class Program {
    static void Main() {
        I obj = new C();
        System.Console.WriteLine(obj.M1());
        System.Console.WriteLine(obj.M2());
    }
}
Run Code Online (Sandbox Code Playgroud)

它在 .NET Core 3.1.402 中产生以下意外输出:

I.M1
C.M2
Run Code Online (Sandbox Code Playgroud)

A没有 的成员的隐式或显式实现I,所以我希望默认实现用于C,因为C继承了 的接口映射A并且没有显式地重新实现I。根据 ECMA-334 (18.6.6) 和 C# 6.0 语言规范: …

c# interface-implementation c#-8.0 default-interface-member

20
推荐指数
1
解决办法
565
查看次数

C#8默认接口实现是否允许多重继承

根据https://blogs.msdn.microsoft.com/dotnet/2018/11/12/building-c-8-0/,C#8中的一个新功能是接口的默认实现.这个新功能是否也隐含地允许多重继承?如果没有,如果我尝试以下操作将会发生什么:

public interface A { int Foo() => 1; }
public interface B { int Foo() => 2; }
public class C : A, B { }
Run Code Online (Sandbox Code Playgroud)

c# oop inheritance c#-8.0 default-interface-member

18
推荐指数
2
解决办法
1370
查看次数

C# 类可以从其自己的实现中调用接口的默认接口方法吗?

如果我有一个像这样的默认接口方法:

public interface IGreeter
{
    void SayHello(string name) => System.Console.WriteLine($"Hello {name}!");
}
Run Code Online (Sandbox Code Playgroud)

我可以让我的具体实现调用该默认方法吗?

public class HappyGreeter : IGreeter
{
    public void SayHello(string name)
    {
        // what can I put here to call the default method?
        System.Console.WriteLine("I hope you're doing great!!");
    }
}
Run Code Online (Sandbox Code Playgroud)

所以调用:

var greeter = new HappyGreeter() as IGreeter;
greeter.SayHello("Pippy");
Run Code Online (Sandbox Code Playgroud)

结果如下:

// Hello Pippy!
// I hope you're doing great!!
Run Code Online (Sandbox Code Playgroud)

事实上,从实现类中调用 C# 接口默认方法表明我可以调用我的类未实现的方法,但正如预期的那样,添加对((IGreeter)this).SayHello(name);内部的调用HappyGreeter.SaysHello会导致堆栈溢出。

c# c#-8.0 default-interface-member

13
推荐指数
1
解决办法
1806
查看次数

默认接口实现.现在,抽象类和接口之间有什么深刻的意义差异?

我知道抽象类是一种无法实例化的特殊类.抽象类只是被分类(继承自).换句话说,它只允许其他类继承它但不能实例化.优点是它为所有子类强制执行某些层次结构.简单来说,它是一种强制所有子类进行相同层次结构或标准的契约.

我也知道An接口不是一个类.它是由Interface这个词定义的实体.接口没有实现; 它只有签名或换言之,只是没有正文的方法的定义.作为与Abstract类相似的一个,它是一个契约,用于为所有子类定义层次结构,或者它定义特定的方法集及其参数.它们之间的主要区别在于类可以实现多个接口,但只能从一个抽象类继承.由于C#不支持多重继承,因此接口用于实现多重继承.

当我们创建一个接口时,我们基本上创建了一组方法,没有必须被实现的类覆盖的任何实现.它的优点是它为类提供了一种方法,使其成为两个类的一部分:一个来自继承层次结构,另一个来自接口.

当我们创建一个抽象类时,我们正在创建一个可能有一个或多个已完成方法的基类,但至少有一个或多个方法未完成并被声明为abstract.如果抽象类的所有方法都未完成,那么它与接口相同.

我注意到我们将在C#8.0中使用默认接口方法

也许我问它因为我只有1 - 2年的编程经验,但现在抽象类和界面之间的主要区别是什么?

我知道我们不能在界面中建立状态,它们之间只有一个区别吗?

c# abstract-class interface c#-8.0 default-interface-member

12
推荐指数
2
解决办法
757
查看次数

自动属性的默认接口方法和默认值

鉴于 auto 属性编译为 a get_method、 aset_method和私有变量,并且自 C# 8 引入默认接口方法以来

接口中的属性可以有默认实现吗?

特别是仅获取属性?

c# c#-8.0 default-interface-member

12
推荐指数
2
解决办法
7386
查看次数

如何调用默认方法而不是具体实现

为什么默认接口方法的行为在 C# 8 中发生了变化?过去的以下代码(当默认接口方法未发布时):

interface IDefaultInterfaceMethod
{
    // By default, this method will be virtual, and the virtual keyword can be here used!
    virtual void DefaultMethod()
    {
        Console.WriteLine("I am a default method in the interface!");
    }

}

interface IOverrideDefaultInterfaceMethod : IDefaultInterfaceMethod
{
    void IDefaultInterfaceMethod.DefaultMethod()
    {
        Console.WriteLine("I am an overridden default method!");
    }
}

class AnyClass : IDefaultInterfaceMethod, IOverrideDefaultInterfaceMethod
{
}

class Program
{
    static void Main()
    {
        IDefaultInterfaceMethod anyClass = new AnyClass();
        anyClass.DefaultMethod();

        IOverrideDefaultInterfaceMethod anyClassOverridden = new AnyClass();
        anyClassOverridden.DefaultMethod();
    } …
Run Code Online (Sandbox Code Playgroud)

c# c#-8.0 default-interface-member

10
推荐指数
1
解决办法
891
查看次数

C#8 接口默认值:如何以良好且可用的方式实现默认属性

我真的很喜欢 C#8 中接口默认实现的想法。但尝试之后却大失所望……

所以这是一个简单的例子,我在 C#8 接口中找到了部分答案,其中定义了属性/方法 - 显然已经不起作用,原因是:

public interface IHasFirstNames
{
    string? FirstName => FirstNames.FirstOrDefault();

    List<string> FirstNames { get; }
}

public class Monster : IHasFirstNames
{
    public List<string> FirstNames { get; } = new();

    public Monster(params string[] firstNames)
    {
        FirstNames.AddRange(firstNames);
    }
}

public static class Program
{
    public static void Main()
    {
        var sally = new Monster("James", "Patrick");

        var error = sally.FirstName; // Cannot resolve symbol FirstName
        var works = ((IHasFirstNames)sally).FirstName;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果你总是不得不把它改得丑陋,那么在接口中拥有属性的默认实现有什么意义呢?

所以根据上面的铸造解决方案我尝试过:

public …
Run Code Online (Sandbox Code Playgroud)

c# interface c#-8.0 default-interface-member

10
推荐指数
1
解决办法
2005
查看次数

使用接口的委托作为参数类型时,逆变无效

考虑带有委托的逆变接口定义:

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

9
推荐指数
1
解决办法
251
查看次数