这是一个简单的类和派生类:
class A { public int val; }
class B : A { }
我喜欢方法Inc
,它适用于A
和B
个实例,它们返回一个val
递增1的新实例。
解决此问题的一种方法是将Inc
定义为扩展方法:
static class Extensions
{
public static T Inc<T>(this T obj) where T : A, new()
{
return new T() { val = obj.val + 1 };
}
}
这似乎有效。在以下示例中,a0.val
11 且b0.val
21 。
var a = new A() { val = 10 };
var b = new B() { val = 20 };
var a0 = a.Inc();
var b0 = b.Inc();
我的问题是,有没有办法将Inc
定义为A
的直接成员并让它按上述方式运作?
如果我这样定义A
:
class A
{
public int val;
public T Inc<T>() where T : A, new()
{
return new T() { val = val + 1 };
}
}
然后,当我致电Inc
时,我需要对该类型进行限定:
var a = new A() { val = 10 };
var b = new B() { val = 20 };
var a0 = a.Inc<A>();
var b0 = b.Inc<B>();
有没有办法去成员方法路线而不必限定类型?
答案 0 :(得分:2)
如果没有在每个子类上实现new
版本的方法,我认为不可能,例如:
class A
{
public int val;
public virtual A Inc()
{
return new A { val = val + 1 };
}
}
class B : A
{
public new B Inc()
{
return new B { val = val + 1 };
}
}
答案 1 :(得分:2)
因此,您实际上想要为某些字段创建具有不同值的对象的克隆:
class A {
public int val;
protected virtual A CloneInternal() {
return (A)MemberwiseClone();
}
public A Inc() {
A a=CloneInternal();
++a.val;
return a;
}
}
class B:A {
public new B Inc() {
return (B)base.Inc();
}
}
static void Main() {
A a=new B();
a=a.Inc();
Console.WriteLine(a.GetType());
}
答案 2 :(得分:1)
abstract class Base
{
public int val { get; set; }
public virtual Base Inc() { return null; }
}
class A : Base
{
public override Base Inc()
{
return new A { val = val + 1 };
}
}
class B : A
{
public override Base Inc()
{
return new B { val = val + 2 };
}
}
使用抽象基类可能更好....
Base bClass = new B();
B bInc = bClass.Inc() as B;
答案 3 :(得分:1)
我不认为这是可能的。您应该提供一个提示,以使编译器猜测T
的正确类型。
您可以尝试使用静态方法:
public static T Inc<T>(T source) where T : A, new()
{
return new T() { val = source.val + 1 };
}
然后,
var b = new B { val = 20 };
var b0 = A.Inc(b);
但这不是一个答案,因为你想要一个成员方法。我宁愿选择扩展方法。
答案 4 :(得分:1)
另一种方式
interface IInc
{
int val { get; set; }
IInc GetNew();
}
class A : IInc
{
public int val
{
get;
set;
}
public virtual IInc GetNew()
{
return new A();
}
public IInc Inc()
{
var newObj = GetNew();
newObj.val++;
return newObj;
}
}
class B : A
{
public override IInc GetNew()
{
return new B();
}
}
并使用
var a = new A() { val = 10 };
var b = new B() { val = 20 };
var a0 = a.Inc();
var b0 = b.Inc();
Console.WriteLine(a0.val);
Console.WriteLine(b0.val);