我有一个接口IStat,它继承了IEquatable和IComparable
与其实际类型相比,各种统计数据主要被称为IStat,而无论实际类型如何,IEquatable和IComparable的实现都是相同的。
IStat.cs
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
// 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;
}
}是否有一种方法可以正确地在IEquatable和IComparable方法中实现IStat?如果没有这样的方法,那么在每个实现中都不必编写相同的方法吗?
编辑
我为Equals、CompareTo和Constructor添加了实现。我知道使用类是处理问题的最佳方法,但是由于软件的限制,我需要使用结构,这就是继承类中默认行为的问题所在。
发布于 2022-07-05 00:24:57
正如@ C# 100所指出的,您可以在C# >= 8.0中这样做,但如果您使用的是较旧的API,并且被迫使用一个尚未具有此功能的语言版本,则需要使用基类、virtual和override关键字,然后按照@AliK的建议在基类中实现默认方法定义。
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;
}
}输出:
Base: 0
Derived: 1如果您确实必须使用结构,则可以将其作为类的组合:
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)}");
}
}
}发布于 2022-07-05 08:40:39
如果不创建方法的两个隐式实现的情况,就不能使用new在接口上隐藏方法。在可能的情况下,您几乎总是应该避免new。
当不能使用基类时,最好的替代方法是这样做:
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();
}现在,您的实现可以用简单的重复锅炉板代码编写。
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,这段代码仍然存在疑问。那不应该是真的。
https://stackoverflow.com/questions/72862773
复制相似问题