Как создать класс записи с конструктором по умолчанию - PullRequest
4 голосов
/ 11 октября 2011

структуры получили конструкторы по умолчанию, как если бы я сделал

type tagONEDEV_FlowRec =
    struct
        .......
    end

Я могу сделать new DeviceModel.tagONEDEV_FlowRec(), но это не работает:

let (<++|) device bytes size =
    let unmanagedPtr = Marshal.AllocHGlobal(size : int)
    Marshal.Copy( (bytes : byte array), 0, unmanagedPtr, size)
    Marshal.PtrToStructure(unmanagedPtr, (device : obj)) // Here
    Marshal.FreeHGlobal(unmanagedPtr)

Мне нужен класс записи здесьalike

[<type:StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)>]
type tagONEDEV_FlowRec = { 
    mutable ....;}

или

type tagONEDEV_FlowRec =
    class
        .......
    end

, но здесь нет конструктора по умолчанию, и структуры очень велики, чтобы обнулять их вручную, так как я могу использовать такие классы с конструкторами по умолчанию?

Если я не найду решение, я думаю, что для меня будет быстрее перекодировать эту часть на C # или даже на VB.NET.Звучит как решение для костыля, но похоже, что я пока не могу набрать номер с помощью F # OOP.

добавление: я не хочу набирать:

               {TimeRec     = 0; 
                Num         = 0us;
                FlagErr     = 0us;
                C6          = 0.0;
                C2H6        = 0.0;
                C3H8        = 0.0;
                CH4         = 0.0;
                CO2         = 0.0;
                iC4H10      = 0.0;
                iC5H12      = 0.0;
                neoC5H12    = 0.0;
                N2          = 0.0;
                nC5H12      = 0.0;
                O2          = 0.0;
                nC4H10      = 0.0;
                He          = 0.0;
                H2          = 0.0;
                H2O         = 0.0;
                id          = 0us; }

<-это то, что я хочу иметь по умолчанию, потому что у меня гораздо больше лагерных структур, чем это, и написание таких конструкторов является злым. </p>

Ответы [ 5 ]

4 голосов
/ 11 октября 2011

Похоже, я нашел рабочий трюк:

[<type:StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)>]
type tagONEDEV_FlowRec =
    class
        [<DefaultValue>] val RecTime         : int;
        [<DefaultValue>] val FlowTime        : int;
        [<DefaultValue>] val AbsPress        : single;
        [<DefaultValue>] val T               : single;
        [<DefaultValue>] val DP_V_FlowRate   : single;
        [<DefaultValue>] val Volume          : double;
        [<DefaultValue>] val Energy          : double;
        [<DefaultValue>] val id              : UInt16;
        new() = {} 
    end
3 голосов
/ 26 января 2012

Если вы по какой-то причине действительно хотите инициализировать запись, как сказал Джон, существуют «хакерские решения».

Вот мой: (Я согласен с тем, что если вы должны сделать это, вы, вероятно, делаете это неправильно, но я уверяю вас, мой действительно помог мне в том, что я делал :)1005 * Конец, вот как бы вы его использовали:

type A = {
  String : string
  Int : int
  StringOption : string Option
}

type B = {
  String : string
  Int : int
  A : A  
}

unsafeDefaultValuesFor<B>

И результат будет выглядеть так: {String = null;Int = 0;A = {String = null;Int = 0;StringOption = null;};}

3 голосов
/ 11 октября 2011

, поскольку jpalmer пытался объяснить, что запись должна быть инициализирована с параметрами. Я думаю, что вы должны попытаться использовать

type MyStruct =
    struct
        val mutable myInt : int
        val mutable myString : string
    end

см. Здесь: Явные поля документов MSDN

да, я знаю, что есть еще строки кода и дополнительные "struct", "end" и некоторые "val", но это действительно так сложно? Если вы используете 1000 свойств для вашего типа, вы все равно должны переосмыслить свой код.

3 голосов
/ 11 октября 2011

В F # вы можете поместить конструктор по умолчанию, используя неявный синтаксис, такой как

type type(arg1,arg2) =
   let v1 = arg1
   let v2 = arg2
   ....

Я думаю, вы используете record, что немного странно, в F # запись похожа на кортежс именованными членами - http://msdn.microsoft.com/en-us/library/dd233184.aspx

РЕДАКТИРОВАТЬ

Таким образом, вопрос в том, можете ли вы иметь конструктор, который обнуляет тип записи - ответ нет.В этом случае я думаю, что лучший ответ - это переключиться с записи на структуру / класс, чтобы вы могли получить желаемое поведение.

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

0 голосов
/ 01 июня 2017

Используйте CLIMutable для объявления записи с неявным конструктором по умолчанию.

[<CLIMutable>]
type MyRecord = { MyField: int }

Чтобы предотвратить смещение кода, я рекомендую следующий стиль в пользу вышеупомянутого.

type [<CLIMutable>] MyRecord = { MyField: int }

«Дрейф кода» - это тенденция отклонения таких вещей, как атрибуты, от элемента кода, для которого он изначально был предназначен, и никто об этом не заметил. Со вторым стилем более вероятно, что атрибут отойдет от объявления из-за небрежности при редактировании.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...