2012-02-17 2 views
4

Как я пытаюсь написать код C# приложение из существующего приложения, но разработанные в Delphi, Очень трудно, но удался, как некоторые до, но теперь я сталкивался с проблемой ...Преобразования Delphi вариант записи в C# структуру

Delphi код содержит следующий код:

type 
    TFruit = record 
    name : string[20]; 
    case isRound : Boolean of // Choose how to map the next section 
     True : 
     (diameter : Single); // Maps to same storage as length 
     False : 
     (length : Single; // Maps to same storage as diameter 
     width : Single); 
    end; 

т.е. вариант записи (с case заявление внутри) и, соответственно, запись строится и его размер тоже. С другой стороны, я пытаюсь сделать то же самое в C# struct, и пока не удалось, я надеюсь, что кое-кто может мне помочь здесь. Так что дайте мне знать, если я могу реализовать это на C#. Заранее спасибо ....

ответ

5

Вы можете использовать явную структуру структуры для репликации этой записи в формате Delphi. Тем не менее, я бы не стал беспокоиться, так как кажется маловероятным, что вам действительно нужно назначить diameter, чтобы назначить также length и наоборот. Эта декларация о записи Delphi выглядит так, как будто она относится к типу кодирования Delphi середины 1990-х годов. Современный код Delphi редко записывался именно так.

Я бы просто сделать это следующим образом:

struct Fruit 
{ 
    string name; 
    bool isRound; 
    float diameter; // only valid when isRound is true 
    float length; // only valid when isRound is false 
    float width; // only valid when isRound is false 
} 

Более элегантный вариант был бы класс со свойствами для каждого поля структуры. И вы соглашаетесь с тем, что свойства getters и seters для 3-х поплавков вызвали исключения, если к ним обратились за недопустимое значение isRound.

+0

Если он использует эту структуру для вызова неуправляемого кода, эта логика не будет работать. – Ani

+1

Нет, но это кажется маловероятным для меня, и в вопросе этого не сказано. В вопросе говорится, что это порт Delphi -> C#. –

1

Возможно, это будет трюк?

Это НЕ решение для копирования и вставки, обратите внимание, что смещения и размеры данных могут потребоваться изменить в зависимости от того, как структура Delphi объявлена ​​и/или выровнена.

[StructLayout(LayoutKind.Explicit)] 
unsafe struct Fruit 
{ 
    [FieldOffset(0)] public fixed char name[20]; 
    [FieldOffset(20)] public bool IsRound; 
    [FieldOffset(21)] public float Diameter; 
    [FieldOffset(21)] public float Length; 
    [FieldOffset(25)] public float Width; 
} 
+1

Две вещи неправильно с этим. C# 'char' - это два байта, но shortstrings Delphi - один байт на символ. И вы не учли выравнивание. Эта запись Delphi будет выровнена, хотя, конечно, настройки компилятора могут повлиять на это. –

+1

Это не было решением для копирования и вставки, но чисто показательным. Я буду обновлять код, чтобы отразить, чем, спасибо. – Ani

+0

Непознанное 'float's довольно странно. Вместо того, чтобы говорить, что они должны быть правильно выровнены, если вам нужно, чтобы они были выложены точно так же, как в Delphi, выровняйте их, и только если они * не совпадают * в Delphi * и *, они должны быть выложены одинаковыми в C# , измените его. – hvd

1

Это зависит от того, что вы пытаетесь сделать.

Если вы просто пытаетесь создать соответствующую структуру, посмотрите на ответ Дэвида Хеффернана. В наши дни существует мало оснований для сопоставления двух полей друг над другом, если они действительно не представляют одно и то же. (Скажем, отдельные элементы или одни и те же элементы в массиве.)

Если вы на самом деле пытаетесь обмениваться файлами, вам нужно просмотреть строки ответа ananthonline, но есть проблема с ним, которая достаточно велика, я не мог оставьте это в комментарии:

Не только проблема с Unicode, но и короткая строка Delphi не имеет соответствующей структуры на C#, и поэтому невозможно просто сопоставить поле поверх нее.

Эта строка [20] фактически содержит байтов, однобайтовый код длины, а затем 20 символов. Вы должны соблюдать код длины, поскольку нет гарантии того, что лежит за пределами указанной длины - вы, вероятно, найдете там мусор. (Подсказка: если запись будет записана на диск, всегда зацикливайте поле перед тем, как вставлять в него новые данные. Это облегчает проверку файла на диске при отладке.)

Таким образом, вам нужно объявить два поля и писать код для обработки на обоих концах.

Поскольку вы должны это делать, я бы пошел дальше и написал код, чтобы справиться с остальной частью, чтобы вообще исключить необходимость в небезопасном коде.

Смежные вопросы