대답은 훌륭 : 여기
class function TPersistGeneric<T>.Init: T;
var
o : TXPersistent; // root class
begin
case PTypeInfo(TypeInfo(T))^.Kind of
tkClass : begin
// xpcreate returns txpersistent, a root class of T
o := XPCreate(GetTypeName(TypeInfo(T))); // has a listed of registered classes
Result := TTypeCast.DynamicCast<TXPersistent, T>(o);
end;
else
result := Default(T);
end;
는 클래스입니다. Delphi에서 제네릭을 실제로 사용하는 데 도움이되었습니다. DynamicCast가 좀 복잡하다면 Andreas를 용서해주십시오. 내가 틀렸다면 나를 바로 잡아주세요. 그러나 다음은 좀 더 간결하고 안전하며 빠르며 (문자열 비교가 없음) 여전히 기능적이어야합니다.
정말로 내가 해왔 던 것은 DynamicCast 유형 params에 대한 클래스 제약 조건을 사용하여 컴파일러가 (보통 클래스가 아닌 매개 변수를 제외하고 원본이되므로) 약간의 작업을 수행하고 TObject.InheritsFrom 함수는 형식 호환성을 검사합니다. 내가 일치하는 클래스의 부모를 트롤링 어딘가에 포인트를 놓친하지 않았다면 나는 또한 매우 유용한 TryCast 함수의 개념을 발견했습니다
(어쨌든 그것은 나를 위해 일반적인 작업입니다!)
이것은 물론입니다 이름 ... IMHO는 약간의 위험이 있습니다. 유형 이름이 다른 범위의 호환되지 않는 클래스와 일치 할 수 있습니다.
어쨌든 여기에 내 코드가 있습니다 (TryCast의 D2009 호환 버전은 이후에 나오는 델파이 XE3에서 작동합니다). D2009 버전을 약속대로
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;
은 (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
이보다 큽니다! – kabstergo