我的C#程序存在问题,其中包括以下内容:
class Program
{
static void Main(string[] args)
{
Child childInstance = Child.ParseFromA(@"path/to/Afile") as Child;
}
}
class Parent{
int property;
public static Parent ParseFromA(string filename)
{
Parent parent = new Parent();
// parse file and set property here...
return parent;
}
}
class Child : Parent
{
public void SomeAdditionalFunction() { }
}
运行此代码时,childInstance
变为null
。
我尝试使用显式演员进行以下作业,但以异常结束:
Child childInstance = (Child)Child.ParseFromA(@"path/to/Afile");
由于我想将某些类型的文件解析为Parent
和Child
实例,我想保留通过静态方法生成实例的设计。
我应该如何获得合适的childInstance
?
答案 0 :(得分:23)
你无法贬低它。将对象创建为r.dbDrop('test').run(conn, function(result) {
console.log(result) // Will result in error
});
后,始终为ReqlOpFailedError: Database 'test' is ambiguous; there are multiple databases with that name in r.dbDrop("test")
。这就像试图将Parent
向下转换为Parent
:这是行不通的 - 这个字符串应该代表哪个字符序列?
因此,您唯一的解决方案是创建正确的对象。我在你的案例中看到的唯一选择是使你的静态方法通用:
new object()
用法:
string
通用约束public static T ParseFromA<T>(string filename) where T : Parent, new()
{
T t = new T();
// parse file and set property here...
return t;
}
确保Child childInstance = Parent.ParseFromA<Child>(@"path/to/Afile");
是T : Parent
的子类型,T
确保Parent
具有无参数构造函数。
答案 1 :(得分:3)
如果您坚持使用静态方法并且不想使用反射或泛型,那么您还可以考虑使用new
关键字:
class Parent
{
public static Parent ParseFromA(string filename)
{
Parent parent = new Parent();
parent.Parse(filename);
return parent;
}
protected virtual void Parse(string fileName)
{
...
}
}
class Child : Parent
{
public new static Child ParseFromA(string filename)
{
Child child = new Child();
child.Parse(filename);
return parent;
}
protected override void Parse(string fileName)
{
base.Parse(fileName);
SomeAdditionalFunction();
}
}
我个人只会使用实例方法。
var child = new Child(...);
child.Parse(...);
额外的代码行是为清洁代码支付的小代价,恕我直言。正如您所看到的,static
关键字在继承方面效果不佳。如果你想要一个单行程序,你也可以总是将实例方法包装到扩展方法中:
public static class ParentEx
{
public static T ParseFile<T>(this T source, string fileName) : where T : Parent
{
source.Parse(fileName);
return source;
}
}
然后
var child = new Child().ParseFile(fileName);
答案 2 :(得分:2)
如果您的静态方法不知道要创建的类型,则需要传递它。例如,使用泛型:
namespace ConsoleApplication18
{
class Program
{
static void Main(string[] args)
{
var childInstance = Parent.ParseAs<Child>(@"path/to/Afile");
childInstance.SomeAdditionalFunction();
}
}
class Parent
{
int property;
public static T ParseAs<T>(string filename) where T : Parent, new()
{
var parent = new T();
// parse file and set property here...
parent.property = 42;
return parent;
}
}
class Child : Parent
{
public void SomeAdditionalFunction() { }
}
}
答案 3 :(得分:1)
您只能转换为父类,而不能转换为子类。编译器无法安全地假设对象已正确构造,具有作为子对象安全访问的所有必要属性。
使用Heinzi上面提到的泛型方法,或者在父类和子类中使用参数化构造函数和实例解析方法。
class Parent
{
public Parent() { }
public Parent(string fileName)
{
Parse(fileName);
}
private void Parse(string fileName)
{
// Do your parsing stuff here.
}
}
class Child : Parent
{
public Child() { }
public Child(string fileName) : base(fileName)
{
// Parsing is done already done within the constructor of Parent, which is called by base(fileName)
// All you need to do here is initialize the rest of your child object.
}
}