C# 重写和新建同时进行
本文关键字:新建 重写 | 更新日期: 2023-09-27 18:33:53
我正在寻找实现以下情况(.NET 3.5(的最佳方法:
interface IGetThing<T>
{
T Get();
}
class BaseGetter<A> : IGetThing<A> where A : new()
{
public virtual A Get()
{
return new A();
}
}
class DerivedGetter<B, A> : Base, IGetThing<B> where B : A, new() where A : new()
{
public override A Get()
{
return Get(); //B version
}
public new virtual B Get()
{
return new B();
}
}
我已经评估了像这样的帖子,但我看不到它会提供等效的解决方案。
我已经看到建议我使用显式接口实现来做类似的事情,但我看不出如何解决继承问题:
如果 Get(( 在这两个地方都显式实现,它将无法解决以下问题:((IGetThing<A>)new DerivedGetter<B, A>()).Get()
调用基方法,而不是所需的派生方法。
尝试在 DerivedGetter 中同时实现 IGetThing 和 IGetThing 会导致编译异常。("DerivedGetter"不能同时实现"IGetThing"和"IGetThing",因为它们可能会统一用于某些类型参数替换(
此外,尝试在DerivedGetter中重新实现BaseGetter的显式实现(IGetThing<A>.Get()
(也提供了一个编译异常(明显的'DerivedGetter.IGetThing<...>。Get((':包含类型不实现接口 'IGetThing'(
目标是在使用派生时隐藏和覆盖基的 Get((。
有人有什么想法吗?
编辑:整体解决方案最好能够扩展到派生类的多层。
顺便说一句,当我从 .NET 4 更改为 .NET 3.5 时,这才开始给我带来编译问题。
这个新的实现会考虑您的意见。我不介意这么说——这很奇怪。
第一件事 - 你必须取消派生 getter 的泛型参数相关的静态泛型约束。您仍然可以检查这一点,但这是一个运行时。
interface IGetThing<T>
{
T Get();
}
class BaseGetter<A> : IGetThing<A> where A : new()
{
public BaseGetter()
{
var generics = this.GetType().GetGenericArguments();
for (var i = 0; i < generics.Length - 1; i++)
{
if (generics[i].BaseType != generics[i+1])
{
throw new ArgumentException(
string.Format("{0} doesn't inherit from {1}",
generics[i].FullName,
generics[i + 1].FullName));
}
}
getters = new Dictionary<Type, Func<object>>();
getters.Add(typeof(A), () => new A());
}
protected readonly IDictionary<Type, Func<object>> getters;
protected object Get(Type type)
{
var types = type.GetGenericArguments();
return getters[types[0]]();
}
public virtual A Get()
{
return (A) Get(this.GetType());
}
}
class DerivedGetter<B, A> : BaseGetter<A>, IGetThing<B>
where B : new() where A : new()
{
public DerivedGetter()
{
getters.Add(typeof(B), () => new B());
}
B IGetThing<B>.Get()
{
return (B) Get(this.GetType());
}
}
class Derived2Getter<C, B, A> : DerivedGetter<B, A>, IGetThing<C>
where C : new() where B : new() where A : new()
{
public Derived2Getter()
{
getters.Add(typeof(C), () => new C());
}
C IGetThing<C>.Get()
{
return (C) Get(this.GetType());
}
}
class Aa { }
class Bb : Aa { }
class Cc : Bb { }
class Dd { }
使用方法(和以前一样! var a = new DerivedGetter((; Console.WriteLine(a.Get(( is Bb(; var b = (IGetThing(a; Console.WriteLine(b.Get(( is Bb(;
var c = new Derived2Getter<Cc, Bb, Aa>();
Console.WriteLine(c.Get() is Cc);
var d = (IGetThing<Bb>)c;
Console.WriteLine(d.Get() is Cc);
var e = (IGetThing<Aa>)c;
Console.WriteLine(e.Get() is Cc);
var f = new DerivedGetter<Dd, Aa>();
输出:
True
True
True
True
True
Unhandled Exception: System.ArgumentException:
ConsoleApplication16.Dd doesn't inherit from
ConsoleApplication16.Aa
下面的旧实现。
我认为你不能用(只是(类型系统做到这一点。您必须通过基类或派生类实现这两个接口。
考虑到这一点,我可能会考虑通过将您想要的行为作为受保护成员注入基类来解决此问题。
像这样: 接口 IGetThing { T Get(); }
class BaseGetter<A> : IGetThing<A> where A : new()
{
protected IGetThing<A> Getter { get; set; }
public virtual A Get()
{
return Getter == null ? new A() : Getter.Get();
}
}
class DerivedGetter<B, A> : BaseGetter<A>, IGetThing<B> where B : A, new() where A : new()
{
public DerivedGetter()
{
Getter = this;
}
public override A Get()
{
return new B();
}
B IGetThing<B>.Get()
{
return (B) Get();
}
}
class Aa { }
class Bb : Aa { }
当运行时,
var a = new DerivedGetter<Bb, Aa>();
Console.WriteLine(a.Get() is Bb);
var b = (IGetThing<Aa>)a;
Console.WriteLine(b.Get() is Bb);
输出:
True
True
经过几个小时的思考和良好的睡眠,我想出了一个可行的解决方案,它保留了原始界面,并扩展到多个继承级别而不会爆炸太多。
interface IGetThing<T>
{
T Get();
}
class BaseGetter<A> : IGetThing<A>
where A : new()
{
public A Get()
{
A result;
GetInternal(out result);
return result;
}
protected virtual void GetInternal(out A target)
{
target = new A();
}
}
class DerivedGetter<B, A> : BaseGetter<A>, IGetThing<B>
where B : A, new()
where A : new()
{
public new B Get()
{
B result;
GetInternal(out result);
return result;
}
protected override void GetInternal(out A target)
{
target = Get();
}
protected virtual void GetInternal(out B target)
{
target = new B();
}
}
class Derived2Getter<C, B, A> : DerivedGetter<B, A>, IGetThing<C>
where C : B, new()
where B : A, new()
where A : new()
{
public new C Get()
{
C result;
GetInternal(out result);
return result;
}
protected override void GetInternal(out B target)
{
target = Get();
}
protected virtual void GetInternal(out C target)
{
target = new C();
}
}
实现运行时:
class Aa { }
class Bb : Aa { }
class Cc : Bb { }
class Program
{
static void Main(string[] args)
{
BaseGetter<Aa> getter = new DerivedGetter<Bb, Aa>();
Console.WriteLine("Type: " + getter.Get().GetType().Name);
getter = new Derived2Getter<Cc, Bb, Aa>();
Console.WriteLine("Type: " + getter.Get().GetType().Name);
}
}
控制台输出为
Type: Bb
Type: Cc