![](/img/trans.png)
[英]How can I create an Instance of a class that is normally generated with a generic method?
[英]How can I downcast an instance generated by static method?
我有一個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
?
你不能低估它。 一旦將對象創建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
的子類型,而new()
確保T
具有無參數構造函數。
如果您堅持使用靜態方法並且不想使用反射或泛型,那么您還可以考慮使用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);
如果靜態方法不知道要創建的類型,則需要傳遞它。 例如,通過使用泛型:
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() { }
}
}
您只能轉換為父類,而不能轉換為子類。 編譯器無法安全地假設對象已正確構造,具有作為子對象安全訪問的所有必需屬性。
要么使用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.
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.