我有一个在f#中映射类的类型,如下所示:
type MyClass =
val myval: integer
new () = {
myval = 0;
}
member self.MyVal with
get () = self.myval
好吧,我想创建这个类的实例。 我可以这样做:
let myinstance = MyClass ()
或
let myinstance = new MyClass ()
有什么区别? 我能同时做到吗?
答案 0 :(得分:8)
从技术上讲,一个区别是你应该在创建new
对象时使用IDisposable
,因为nyinyithann已经解释过了。另一个区别是您可以在创建泛型类型时省略类型参数:
// Works and creates Dictionary<int, string>
let r1 = System.Collections.Generic.Dictionary 10
r1.Add(10, "A")
// You get a compiler error when you write this:
let r2 = new System.Collections.Generic.Dictionary 10
r2.Add(10, "A")
除了这两件事之外,没有任何技术差异(当您编写或省略new
时,生成的IL肯定没有区别。)
你应该使用哪一个?这是一个风格问题。任何F#编码标准都没有涵盖这一点,因此这取决于您的偏好。现在我正在考虑它,我自己可能没有非常一致的风格。我认为在使用new
创建要分配给值的实例时,我通常会使用let
:
let rnd = new Random()
但是,在创建要用作参数的对象时,我通常不会使用new
(例如,在以下示例中为Size
或Point
):
let frm = new Form(Size = Size(600, 400))
let gr = frm.CreateGraphics()
gr.FillRectangle(Brushes.Red, Rectangle(Point(0, 0), Point(100, 100)))
可能,我也更喜欢将new
用于更复杂的类型,并避免使用简单类型或.NET值类型(但我不认为我这样做过于一致)。
答案 1 :(得分:2)
对于实现IDisposable的类型,应使用new进行实例化。否则,您将收到以下编译警告。
建议使用“new Type(args)”而不是“Type(args)”创建支持IDisposable接口的对象,以指示资源可能由生成的值拥有
答案 2 :(得分:2)
没有区别。这两个调用都将创建一个具有完全相同IL代码的新对象。
.method public static void main@() cil managed
{
.entrypoint
// Code size 26 (0x1a)
.maxstack 4
.locals init ([0] class Program/MyClass myinstance,
[1] class Program/MyClass myinstance2)
IL_0000: nop
IL_0001: newobj instance void Program/MyClass::.ctor()
IL_0006: dup
IL_0007: stsfld class Program/MyClass '<StartupCode$fsharpapp>'.$Program::myinstance@11
IL_000c: stloc.0
IL_000d: newobj instance void Program/MyClass::.ctor()
IL_0012: dup
IL_0013: stsfld class Program/MyClass '<StartupCode$fsharpapp>'.$Program::myinstance2@12
IL_0018: stloc.1
IL_0019: ret
} // end of method $Program::main@
要反编译二进制文件,您可以使用.NET Framework SDK的ildasm,它在您打开Visual Studio命令提示符时位于路径中。
ildasm /CAVERBAL /out=fsharp.il fsharpapp.exe
选项CAVERBAL会以通常的方式打印人类可读形式的属性内容,而不是二进制blob。