Class 如何使用默认构造函数创建记录类
结构得到了默认构造函数,就像我得到的一样Class 如何使用默认构造函数创建记录类,class,f#,constructor,struct,Class,F#,Constructor,Struct,结构得到了默认构造函数,就像我得到的一样 type tagONEDEV_FlowRec = struct ....... end 我可以执行新建设备模型.tagONEDEV\u FlowRec(),但它不适用于此: let (<++|) device bytes size = let unmanagedPtr = Marshal.AllocHGlobal(size : int) Marshal.Copy( (bytes : byte arr
type tagONEDEV_FlowRec =
struct
.......
end
我可以执行新建设备模型.tagONEDEV\u 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)
但是这里没有默认构造函数,结构非常大,可以手动初始化为零,所以如何将这些类与默认构造函数一起使用
如果我找不到解决方案,我想在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; }
在F#中,可以使用隐式语法放置默认构造函数,如
type type(arg1,arg2) =
let v1 = arg1
let v2 = arg2
....
我认为您使用的record
方式有点奇怪,在F#中,记录类似于具有命名成员的元组-
编辑
所以问题基本上是你能有一个将记录类型归零的构造函数吗?答案是否定的。在这种情况下,我认为最好的答案是从一个记录切换到一个结构/类,这样你就可以得到你想要的行为
我想到的一个黑客解决方案是使用
System.Reflection.Assembly.CreateInstance
,它有时可以帮助处理类似的事情,但编译器没有提供默认构造函数,因此它无法工作,因为jpalmer试图解释必须使用参数初始化记录。我想你应该试着用
type MyStruct =
struct
val mutable myInt : int
val mutable myString : string
end
请看这里:
是的,我知道有更多的代码行和一个额外的“struct”、“end”和一些“val”,但这真的有这么难吗?如果你在你的类型上使用1000个属性,你无论如何都应该重新考虑你的代码。似乎我找到了一个有效的窍门:
[<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
[]
类型tagONEDEV_FlowRec=
班
[]val RecTime:int;
[]val-FlowTime:int;
[]按下键:单个;
[]val T:单个;
[]val DP_V_流量:单个;
[]val音量:双倍;
[]val能量:双倍;
[]val id:UInt16;
new()={}
结束
如果您出于某种原因确实想初始化一条记录,正如John所说,有
“黑客解决方案”
这是我的:(我同意如果你必须这样做,你可能做错了,但我向你保证,我的建议确实对我所做的有帮助:)
让rec记录错误值(x:System.Type)=
如果为x.IsValueType,则为System.Activator.CreateInstance(x)
否则如果(Microsoft.FSharp.Reflection.FSharpType.IsRecord x),则
让cntr=x.GetConstructors()|>Array.pick一些
设值=
cntr.GetParameters()
|>Array.map(乐趣p->p.ParameterType)
cntr.Invoke(值)
否则如果是(Microsoft.FSharp.Reflection.FSharpType.IsTuple(x)),则
设tupleValues=
Microsoft.FSharp.Reflection.FSharpType.GetTupleElements(x)
|>Array.map(默认值)
Microsoft.FSharp.Reflection.FSharpValue.MakeTuple(tupleValue,x)
否则如果(x.IsArray)那么
框(System.Array.CreateInstance(x.GetElementType(),0))
其他的
无效的
让我们为:?>“a”设置一个默认值
以下是您将如何使用它:
type A = {
String : string
Int : int
StringOption : string Option
}
type B = {
String : string
Int : int
A : A
}
unsafeDefaultValuesFor<B>
A型={
字符串:字符串
Int:Int
StringOption:string选项
}
B类={
字符串:字符串
Int:Int
A:A
}
未列出的错误值
结果是这样的:
{String=null;Int=0;A={String=null;Int=0;StringOption=null;};}使用CLIMutable声明具有隐式默认构造函数的记录
[<CLIMutable>]
type MyRecord = { MyField: int }
[]
键入MyRecord={MyField:int}
为了防止代码漂移,我推荐下面的样式来支持上面的样式
type [<CLIMutable>] MyRecord = { MyField: int }
type[]MyRecord={MyField:int}
“代码漂移”是指像属性这样的东西在没有任何人注意到的情况下,从它最初打算用于的代码元素漂移出去的趋势。对于第二种样式,由于编辑时的疏忽,属性不太可能偏离声明。不,这需要做很多工作。我需要没有参数的默认空构造函数。我有一个类,里面有一些结构数组和许多成员/值。我不想为它编写1000行代码构造函数。这不会有他想要的默认构造函数,但通过添加
new()=…
member@Veronica-您必须从记录切换到类/结构查看我的更新答案如果我有一个大的结构或记录类型,则不意味着我需要重新编码。当我使用struct而不是class时,我在PtrToStructure上得到了错误消息:这个结构不应该是类值。参数名:structure。这就是为什么我在寻找类的默认构造函数,而不是使用结构。检查问题更新,我描述了我所说的“真的这么难”对不起,但你问题的第一点是你创建了一个结构,所以我选择了这个。您不能指望我们运行您的部分代码来查找所有警告。我读到你的描述是“defaultconstructor”的问题,而不是结构的问题(在看到你对第一个答案的抱怨之后)。正如您所看到的,您的解决方案基本相同(只是您必须添加DefaultValue Attrib)-我猜您是从我提供的链接中获取解决方案的-对吗很抱歉,如果这没有按预期帮助您。是的,我在提供的链接中找到了解决方案。在您的示例中,您使用的是struct,由于PtrToStructure,我不允许使用它。行new()={}实现了我想要的,DefaultValue允许我不写大的构造函数代码。只做一些类似于let inline z:'t=fun\uuz->LanguagePrimitives.GenericZero
的事情可能会少一些,然后你就可以编写val-value:int=z()
,这样可以节省一些时间typing@jpalmer []对我来说似乎更好,我不打字,我复制粘贴…有一刻我已经不需要了,但我真的很喜欢你的解决方案
type A = {
String : string
Int : int
StringOption : string Option
}
type B = {
String : string
Int : int
A : A
}
unsafeDefaultValuesFor<B>
[<CLIMutable>]
type MyRecord = { MyField: int }
type [<CLIMutable>] MyRecord = { MyField: int }