首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有没有一种方法可以在不同的接口中“实现”一个接口?

有没有一种方法可以在不同的接口中“实现”一个接口?
EN

Stack Overflow用户
提问于 2022-07-04 23:29:36
回答 2查看 87关注 0票数 2

我有一个接口IStat,它继承了IEquatableIComparable

与其实际类型相比,各种统计数据主要被称为IStat,而无论实际类型如何,IEquatableIComparable的实现都是相同的。

IStat.cs

代码语言:javascript
复制
public interface IStat : IEquatable<IStat>, IComparable<IStat>{
    string GetKey();
    string GetValue();
    public new bool Equals(IStat stat) { // I'm aware I shouldn't use new
        return stat is not null && GetKey() == stat.GetKey();
    }
    public new int CompareTo(IStat stat) {
        return stat is null?1:GetKey.CompareTo(stat.GetKey());
    }
}

public interface IStat<TKey, TValue> : IStat {
    TKey Key{get;}
    TValue Value{get;}
}

ExampleStat.cs

代码语言:javascript
复制
// still requires implementation of Equals and CompareTo, and ExampleStat must be a struct
public struct ExampleStat : IStat<string, double> {
    private string m_Key;
    private double m_Value;
    public string Key=>m_Key;
    public double Value=>m_Value;
    public ExampleStat(string key, double value) {
        m_Key = key;
        m_Value = value;
    }
 }

是否有一种方法可以正确地在IEquatableIComparable方法中实现IStat?如果没有这样的方法,那么在每个实现中都不必编写相同的方法吗?

编辑

我为Equals、CompareTo和Constructor添加了实现。我知道使用类是处理问题的最佳方法,但是由于软件的限制,我需要使用结构,这就是继承类中默认行为的问题所在。

EN

回答 2

Stack Overflow用户

发布于 2022-07-05 00:24:57

正如@ C# 100所指出的,您可以在C# >= 8.0中这样做,但如果您使用的是较旧的API,并且被迫使用一个尚未具有此功能的语言版本,则需要使用基类、virtualoverride关键字,然后按照@AliK的建议在基类中实现默认方法定义。

代码语言:javascript
复制
List<IStat> stats = new();
stats.Add(new StatBase());
stats.Add(new StatDerived());
foreach(var stat in stats)
{
    Console.WriteLine($"{stat.GetKey()}: {stat.CompareTo(stat)}");
}

public interface IStat : IComparable<IStat>
{
    public string GetKey();
}

public class StatBase : IStat
{
    public virtual string GetKey()
    { // default definition
        return "Base";
    }

    public virtual int CompareTo(IStat? stat)
    {
        return 0;
    }
}

public class StatDerived : StatBase
{
    public override string GetKey()
    { // derived definition
        return "Derived";
    }

    public override int CompareTo(IStat? stat)
    {
        return 1;
    }
}

输出:

代码语言:javascript
复制
Base: 0
Derived: 1

如果您确实必须使用结构,则可以将其作为类的组合:

代码语言:javascript
复制
AStruct aStruct = new AStruct();
aStruct.PrintStuff();

public struct AStruct
{
    private List<IStat> stats = new();
    public AStruct()
    {
        stats.Add(new StatBase());
        stats.Add(new StatDerived());
    }
    public void PrintStuff()
    {
        foreach (var stat in stats)
        {
            Console.WriteLine($"{stat.GetKey()}: {stat.CompareTo(stat)}");
        }
    }
}
票数 0
EN

Stack Overflow用户

发布于 2022-07-05 08:40:39

如果不创建方法的两个隐式实现的情况,就不能使用new在接口上隐藏方法。在可能的情况下,您几乎总是应该避免new

当不能使用基类时,最好的替代方法是这样做:

代码语言:javascript
复制
public interface IStat : IEquatable<IStat>, IComparable<IStat>
{
    public static class Default
    {
        public static bool Equals(IStat lhs, IStat rhs) => lhs is not null && lhs.GetKey() == rhs.GetKey();
        public static int CompareTo(IStat lhs, IStat rhs) => lhs is null ? 1 : lhs.GetKey().CompareTo(rhs.GetKey());
    }

    string GetKey();
    string GetValue();
}

现在,您的实现可以用简单的重复锅炉板代码编写。

代码语言:javascript
复制
public struct ExampleStat : IStat<string, double>
{
    private string m_Key;
    private double m_Value;
    public string Key => m_Key;
    public double Value => m_Value;

    public ExampleStat(string key, double value)
    {
        m_Key = key;
        m_Value = value;
    }

    string IStat.GetKey() => this.Key;
    string IStat.GetValue() => this.Value.ToString();

    public bool Equals(IStat other) => IStat.Default.Equals(this, other);
    public int CompareTo(IStat other) => IStat.Default.CompareTo(this, other);

}

在我看来,作为new ExampleStat("Hello", 1.0).Equals(new ExampleStat("Hello", 2.0)) == true,这段代码仍然存在疑问。那不应该是真的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72862773

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档