You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求帮助将C#代码移植到Delphi,解决TArray泛型相关问题

C#数组序列化逻辑移植到Delphi的TArray泛型处理问题

我在把一段C#代码移植到Delphi时,遇到了TArray泛型类型相关的问题。目前已经完成了Int32、Int64、UInt32等基础类型的WriteValue逻辑实现,但在处理数组部分时卡住了。附上C#原代码和我写的不完整Delphi代码,求WriteVector后续代码的正确写法。

C#原代码

internal static void WriteValue(object value, Type valueType)
{
    var type = value.GetType();
    switch (Type.GetTypeCode(type))
    {   
        // 以下基础类型已在Delphi中实现
        case TypeCode.Int32: Write((int)value); break;
        case TypeCode.Int64: Write((long)value); break;
        case TypeCode.UInt32:Write((uint)value); break;
        case TypeCode.UInt64:Write((ulong)value); break;
        case TypeCode.Double:Write((double)value); break;
        case TypeCode.Object:
            if (type.IsArray)   
                // 问题出在这里
                WriteVector((Array)value);
            break;
        default:
            break;
    }
}
            
internal static void WriteVector(Array array)
{
    if (array == null) { return; }
    int count = array.Length;
    // 保存数组长度
    var elementType = array.GetType().GetElementType();
    for (int i = 0; i < count; i++)
        WriteValue(array.GetValue(i), elementType);
}   

我的Delphi代码(不完整)

// 我的Delphi代码  
procedure WriteValue(Value: TValue; valueType: PTypeInfo);
begin
    case Value.Kind of
    tkArray:
      WriteVector(Value.AsType<TArray>);
    end;
end;
    
procedure WriteVector(array: TArray);
var
    count: Integer;
    i: Integer;
begin
      if array = nil then
      begin
          Exit;
      end;
      // count := Length(array);
      // 保存count值
      // 后续代码该怎么写?
end;

解决方案

Delphi中的TArray是泛型容器,不能直接作为无类型参数传递,且Delphi区分静态数组(tkArray)和动态数组(tkDynArray),需要结合RTTI来实现类似C#的通用数组处理逻辑。以下是修正后的完整代码:

修正后的WriteValue

procedure WriteValue(Value: TValue; ValueType: PTypeInfo);
begin
  case Value.Kind of
    tkInteger: Write(Value.AsInteger);
    tkInt64: Write(Value.AsInt64);
    tkUInt32: Write(Value.AsUInt32);
    tkUInt64: Write(Value.AsUInt64);
    tkFloat: Write(Value.AsDouble);
    tkArray, tkDynArray: // 同时处理静态和动态数组
      WriteVector(Value);
    // 其他类型可根据需求扩展
  end;
end;

完整实现的WriteVector

uses
  System.Rtti, System.TypInfo;

procedure WriteVector(const ArrayValue: TValue);
var
  Context: TRttiContext;
  ArrayType: TRttiArrayType;
  DynArrayType: TRttiDynamicArrayType;
  ElementType: PTypeInfo;
  I: Integer;
  ElementValue: TValue;
  ArrayLength: Integer;
begin
  if not ArrayValue.IsArray then
    Exit;

  // 获取数组长度和元素类型
  case ArrayValue.Kind of
    tkArray:
      begin
        ArrayType := Context.GetType(ArrayValue.TypeInfo) as TRttiArrayType;
        // 计算一维静态数组的长度
        ArrayLength := ArrayType.Dimensions[0].Range.Max - ArrayType.Dimensions[0].Range.Min + 1;
        ElementType := ArrayType.ElementType.Handle;
      end;
    tkDynArray:
      begin
        DynArrayType := Context.GetType(ArrayValue.TypeInfo) as TRttiDynamicArrayType;
        ArrayLength := DynArrayType.GetLength(ArrayValue.GetReferenceToRawData);
        ElementType := DynArrayType.ElementType.Handle;
      end;
  else
    Exit;
  end;

  // 写入数组长度(假设Write已实现Integer类型的写入)
  Write(ArrayLength);

  // 遍历数组元素,递归调用WriteValue
  for I := 0 to ArrayLength - 1 do
  begin
    ElementValue := ArrayValue.GetArrayElement(I);
    WriteValue(ElementValue, ElementType);
  end;
end;

关键说明

  1. 数组类型区分:Delphi需要分别处理静态数组(tkArray)和动态数组(tkDynArray),两者的长度获取方式不同
  2. RTTI的使用:通过TRttiContext获取数组的类型元数据,包括元素类型、数组维度/长度
  3. 元素遍历:使用TValue.GetArrayElement直接获取数组中指定索引的元素,无需手动转换类型
  4. 递归调用:和C#逻辑一致,对每个数组元素递归调用WriteValue完成序列化

内容的提问来源于stack exchange,提问作者Sdean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 01:35:35