gpt4 book ai didi

c# - 在 C# 中模拟基数分配有多接近

转载 作者:行者123 更新时间:2023-11-30 20:20:13 24 4
gpt4 key购买 nike

我想创建一个Func,它是一些派生类的base.Equals 方法的双参数封装。 Func 的一个参数是调用 base.Equals 的实例,而 Func 的另一个参数被传递到 base.Equals。我不能对基类提出要求,但我可以对派生类提出一些要求。例如,我可以要求派生类公开 base.Equals

如果关键字 base 可以像关键字 this 一样使用,这将很容易,但事实并非如此。在下面查看我失败的尝试。

using System;
namespace MyNamespace {
class BaseClass { }
class DerivedClass : BaseClass, IEquatable<DerivedClass> {
Func<DerivedClass, DerivedClass, bool> baseEquals;
DerivedClass() {
DerivedClass referenceToThis = this;
BaseClass referenceToBase = referenceToThis.base; // doesn't compile
this.baseEquals = (x, y) => x.Equals(y);
}
public bool Equals(DerivedClass that) => this.baseEquals(this, that);
}
}

以我目前对C#的理解,我认为想做的事情是不允许的。

Is there C# that has the same semantics as my example but is valid?

If not, how close can one get to this example? That is, to what extent can the base.Equals method be encapsulated?

编辑以添加示例

using System;
using FluentEquality.Common.EqualityCompareres;
namespace MyNamespace {
class MyProgram {
static void Main(string[] args) {
var instance0 = new LeafClass(0);
var instance1 = new LeafClass(1);
var baseEqualsMethod = SomeMagicalMethodYetToBeDefined(instance0.BaseEqualsMethod, instance0.BaseGetHashCodeMethod);
equalityComparer.Equals(instance0, instance1); // should output: BaseClass 0
equalityComparer.Equals(instance1, instance0); // should output: BaseClass 1
Console.ReadKey();
}
}
class BaseClass {
protected int Id;
public BaseClass(int id) { this.Id = id; }
public override bool Equals(object obj) { Console.WriteLine(nameof(BaseClass) + " " + Id); return false; }
public override int GetHashCode() => base.GetHashCode();
}
class DerivedClass : BaseClass {
public DerivedClass(int id) : base(id) { }
public override bool Equals(object obj) { Console.WriteLine(nameof(DerivedClass) + " " + Id); return false; }
public override int GetHashCode() => base.GetHashCode();
public Func<object, bool> BaseEqualsMethod => base.Equals;
public Func<int> BaseGetHashCodeMethod => base.GetHashCode;
}
class LeafClass : DerivedClass {
public LeafClass(int id) : base(id) { }
public override bool Equals(object obj) { Console.WriteLine(nameof(LeafClass) + " " + Id); return false; }
public override int GetHashCode() => base.GetHashCode();
}
}

最佳答案

因此,我的另一个答案存在致命缺陷,因为它存在与反射相同的问题 - 无论您尝试调用哪种方法,都会调用覆盖的方法。

以下是使用发现的技术的示例 here创建一个动态方法,确实允许您指定要调用哪个重写方法。这种方法的好处是您不需要类来公开基方法,事实上,您根本不需要修改类。

class BaseClass
{
public override bool Equals(object other)
{
Console.WriteLine("BaseClass");
return false;
}
}

class DerivedClass
{
public bool Equals(DerivedClass other)
{
Console.WriteLine("DerivedClass Equals");
return true;
}

public override bool Equals(object other)
{
Console.WriteLine("DerivedClass Object Equals");
return true;
}
}

static class MyComparerThing<TParentType>
{
public static bool Equals(TParentType left, TParentType right) => MyComparerThing<TParentType, TParentType, object>.Equals(left, right);
}
static class MyComparerThing<TParentType, TOnType>
{
public static bool Equals(TOnType left, TOnType right) => MyComparerThing<TParentType, TOnType, object>.Equals(left, right);
}
static class MyComparerThing<TParentType, TOnType, TCompareType>
{
static Func<TOnType, TOnType, bool> baseEquals;

static MyComparerThing()
{
DynamicMethod dm = new DynamicMethod("BaseFoo", typeof(bool), new Type[] { typeof(TOnType), typeof(TOnType) }, typeof(TOnType));
ILGenerator gen = dm.GetILGenerator();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);

var method = typeof(TParentType).GetMethod("Equals", new[] { typeof(TCompareType) });
gen.Emit(OpCodes.Call, method);
gen.Emit(OpCodes.Ret);

baseEquals = (Func<TOnType, TOnType, bool>)dm.CreateDelegate(typeof(Func<TOnType, TOnType, bool>));
}

public static bool Equals(TOnType left, TOnType right) => baseEquals(left, right);
}

使用以下内容进行测试:

void Main()
{
var a = new DerivedClass();
var b = new DerivedClass();

//The generic parameters in order are:
//1. The type which implements the desired method
//2. The type of the arguments (a and b)
//3. The parameter argument of the method (object vs DerivedClass)

//The following three are equivelant, using 'default' generic arguments
MyComparerThing<DerivedClass>.Equals(a, b);
MyComparerThing<DerivedClass, DerivedClass>.Equals(a, b);
MyComparerThing<DerivedClass, DerivedClass, object>.Equals(a, b);

//This will print the method declared in BaseClass. a and b are still DerivedClass instances. This is the one you're wanting to use
MyComparerThing<BaseClass, DerivedClass>.Equals(a, b);

//This will print the method declared in DerivedClass, with the DerivedClass overload
MyComparerThing<DerivedClass, DerivedClass, DerivedClass>.Equals(a, b);

//This will print the method declared in DerivedClass, with the object overload
MyComparerThing<DerivedClass, DerivedClass, object>.Equals(a, b);

}

打印:

DerivedClass Object Equals
DerivedClass Object Equals
DerivedClass Object Equals
BaseClass
DerivedClass Equals
DerivedClass Object Equals

我选择使用泛型来决定调用哪个覆盖 - 但可以更改此设置以从其他地方提取信息,或者硬编码。如果你想总是调用基本方法,你需要修改上面的内容,按照 typeof(TOnType).BaseType.GetMethod("Equals", ....)

关于c# - 在 C# 中模拟基数分配有多接近,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37266637/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com