2011-02-13 70 views
4

我有一個類型的映射在F#類如下:實例化類型:何時使用新?

type MyClass = 
    val myval: integer 
    new() = { 
     myval = 0; 
    } 
    member self.MyVal with 
     get() = self.myval 

好吧,我想創建這個類的一個實例。 我可以這樣做:

let myinstance = MyClass() 

let myinstance = new MyClass() 

有什麼區別? 我可以同時做嗎?

回答

2

對於實現IDisposable的類型應該使用new實例化。否則,您將收到以下編譯警告。

建議支持IDisposable接口的對象是使用「新類型(參數)」,而不是「Type(參數)」,表明資源可能產生的價值

+1

我沒想到這是唯一的區別:)謝謝。 – Andry 2011-02-13 14:34:23

2

所擁有沒有創建區別。這兩個調用都將創建一個具有完全相同IL代碼的新對象。

.method public static void [email protected]() 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::[email protected] 
    IL_000c: stloc.0 
    IL_000d: newobj  instance void Program/MyClass::.ctor() 
    IL_0012: dup 
    IL_0013: stsfld  class Program/MyClass '<StartupCode$fsharpapp>'.$Program::[email protected] 
    IL_0018: stloc.1 
    IL_0019: ret 
} // end of method $Program::[email protected] 

要反編譯二進制文件,可以在打開Visual Studio命令提示符時使用位於路徑中的.NET Framework SDK的ildasm。

ildasm /CAVERBAL /out=fsharp.il fsharpapp.exe 

CAVERBAL選項不像往常一樣打印屬於人類可讀形式的屬性內容,而不是二進制blob。

+0

謝謝Alois ...抱歉有一個問題,我使用IL Dissassembler,但我得到一棵樹,查看完整的il代碼,我該怎麼辦? – Andry 2011-02-13 14:39:54

+0

在ildasm文件 - >轉儲。它會顯示你想要在你的反彙編代碼中的項目列表,並且OK'ing提示你輸入文件名來轉儲IL代碼 – Hakeem 2011-02-13 15:40:58

8

從技術上講,一個不同之處在於,您應該在創建IDisposable對象時使用new,因爲已經解釋了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") 
從這兩件事

除此之外,沒有技術差異(且有一定的產生IL沒什麼區別,當你寫或省略new) 。

你應該在什麼時候使用?這是一個風格問題。這不包含在任何F#編碼標準中,因此這取決於您的偏好。現在我正在考慮這個問題,我自己可能沒有非常一致的風格。我想創建實例時一般使用new要分配使用let爲值:

let rnd = new Random() 

然而,我通常不創建對象時,可以使用作爲參數(例如,在下面的例子中SizePoint使用new ):

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值類型(但我不認爲我這樣做太一致)。