以上來自安德烈亞斯答案是輝煌的。這真的幫助我在Delphi中使用泛型。請原諒我Andreas,因爲我想知道DynamicCast是否有點複雜。如果我錯了,請糾正我,但以下內容應該更簡潔,安全,快速(無字符串比較),並且仍然可以正常工作。
真的,我所做的一切就是使用DynamicCast類型參數上的類約束來允許編譯器做一些工作(因爲原始文件總是除非使用非類參數),然後使用TObject.InheritsFrom函數來檢查類型兼容性。
我還發現一個TryCast功能非常有用的想法(這對我來說是常見的任務呢!)
這是當然的,除非我在拖網類父母匹配錯了地方名稱...哪些恕我直言有點危險,因爲類型名稱可能匹配不同範圍內的不兼容類。
無論如何,這裏是我的代碼(適用於Delphi XE3 ... D2009兼容版本的TryCast)。
type
TTypeCast = class
public
// ReinterpretCast does a hard type cast
class function ReinterpretCast<ReturnT>(const Value): ReturnT;
// StaticCast does a hard type cast but requires an input type
class function StaticCast<T, ReturnT>(const Value: T): ReturnT;
// Attempt a dynamic cast, returning True if successful
class function TryCast<T, ReturnT: class>(const Value: T; out Return: ReturnT): Boolean;
// DynamicCast is like the as-operator. It checks if the object can be typecasted
class function DynamicCast<T, ReturnT: class>(const Value: T): ReturnT;
end;
implementation
uses
System.SysUtils;
class function TTypeCast.ReinterpretCast<ReturnT>(const Value): ReturnT;
begin
Result := ReturnT(Value);
end;
class function TTypeCast.StaticCast<T, ReturnT>(const Value: T): ReturnT;
begin
Result := ReinterpretCast<ReturnT>(Value);
end;
class function TTypeCast.TryCast<T, ReturnT>(const Value: T; out Return: ReturnT): Boolean;
begin
Result := (not Assigned(Value)) or Value.InheritsFrom(ReturnT);
if Result then
Return := ReinterpretCast<ReturnT>(Value);
end;
class function TTypeCast.DynamicCast<T, ReturnT>(const Value: T): ReturnT;
begin
if not TryCast<T, ReturnT>(Value, Result) then
//Value will definately be assigned is TryCast returns false
raise EInvalidCast.CreateFmt('Invalid class typecast from %s(%s) to %s',
[T.ClassName, Value.ClassName, ReturnT.ClassName]);
end;
由於承諾的D2009版本(需要一些小的努力才能到達ReturnT類)。
class function TTypeCast.TryCast<T, ReturnT>(const Value: T; out Return: ReturnT): Boolean;
var
LReturnTypeInfo: PTypeInfo;
LReturnClass: TClass;
begin
Result := True;
if not Assigned(Value) then
Return := Default(ReturnT)
else
begin
LReturnTypeInfo := TypeInfo(ReturnT);
LReturnClass := GetTypeData(LReturnTypeInfo).ClassType;
if Value.InheritsFrom(LReturnClass) then
Return := ReinterpretCast<ReturnT>(Value)
else
Result := False;
end;
end;
太糟糕了我不能將此標記爲最喜歡的答案... – gabr 2009-05-29 19:59:46