假设您有两个类,如下例所示。
如何修改SplitObject,使其始终返回类型为t的对象,例如在Main()中,它应返回DerivedClass类型的对象?
我猜这个解决方案会涉及反思吗?我还没有学到任何有关反射的知识,所以我不知道这是如何工作的。
public class BaseClass
{
float _foo;
public BaseClass(float foo){_foo = foo}
public BaseClass SplitObject()
{
Type t = GetType();
// Do something with t
_foo = _foo/2f;
return new BaseClass(_foo); // I want to construct an
// object of type t instead
// of type BaseClass
}
}
public class DerivedClass : BaseClass
{
public DerivedClass(float foo) : base(foo){}
}
class Program
{
static void Main()
{
BaseClass foo = new DerivedClass(1f);
BaseClass bar = foo.SplitObject(); // should return a DerivedObject
}
}
答案 0 :(得分:1)
不需要反射 - 只需将SplitObject()
设为虚拟,并在派生类中以不同方式实现它。
另一种选择是将Split行为提取到界面中,比如说ISplittable<T>
public class BaseClass
{
public virtual BaseClass SplitObject()
{
BaseClass splitObject = new BaseClass();
//initialize the split object
return splitObject;
}
}
public class DerivedClass : BaseClass
{
public override BaseClass SplitObject()
{
DerivedClass derivedSplitObject = new DerivedClass();
//initialize the derived split object
return derivedSplitObject;
}
}
}
答案 1 :(得分:1)
如果您真的想使用反射,可以执行以下操作:
return (BaseClass)Activator.CreateInstance(GetType(), _foo);
当然,现在有一个隐式契约,所有派生类都必须实现这样的构造函数。不幸的是,这种合同无法在当前的类型系统中指定;所以在编译时不会发现违规行为。使用erash的想法会好得多。我会做类似的事情:
//... Base class:
public BaseClass SplitObject()
{
_foo = _foo / 2f;
return NewInstance(_foo);
}
protected virtual BaseClass NewInstance(float foo)
{
return new BaseClass(foo);
}
//... Derived class:
protected override BaseClass NewInstance(float foo)
{
return new DerivedClass(foo);
}
答案 2 :(得分:1)
如果您只希望代码出现在一个地方(更适合维护,特别是如果有许多派生类型),您将需要使用反射:
public class BaseClass
{
float _foo;
public BaseClass(float foo){_foo = foo;}
public BaseClass SplitObject()
{
Type t = GetType();
_foo = _foo / 2f;
//Find the constructor that accepts float type and invoke it:
System.Reflection.ConstructorInfo ci = t.GetConstructor(new Type[]{typeof(float)});
object o=ci.Invoke(new object[]{_foo});
return (BaseClass)o;
}
}
public class DerivedClass : BaseClass
{
public DerivedClass(float foo) : base(foo) { }
}
class Program
{
static void Main()
{
BaseClass foo = new DerivedClass(1f);
//Cast the BaseClass to DerivedClass:
DerivedClass bar = (DerivedClass)foo.SplitObject();
}
}