开发者

Instantiating types: when using new?

开发者 https://www.devze.com 2023-02-10 18:33 出处:网络
I have a type mapping a class in f# as follows: type MyClass = val myval: 开发者_StackOverflow社区integer

I have a type mapping a class in f# as follows:

type MyClass =
   val myval: 开发者_StackOverflow社区integer
   new () = {
      myval = 0;
   }
   member self.MyVal with
      get () = self.myval

Well, I want to create an instance of this class. I can do so:

let myinstance = MyClass ()

or

let myinstance = new MyClass ()

What's the difference? Can I do both?


Technically, one difference is that you should use new when creating IDisposable objects as nyinyithann already explained. Another difference is that you can omit type arguments when creating generic type:

// 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")

Aside from these two things, there is no technical difference (and there is certainly no difference in the generated IL when you write or omit new).

Which one should you use when? This is a matter of style. This is not covered by any F# coding standards, so it depends on your preference. Now that I'm thinking about it, I probably don't have very consistent style myself. I think I generally use new when creating instances to be assigned to value using let:

let rnd = new Random()

However, I usually don't use new when creating objects to be used as arguments (e.g. Size or Point in the following example):

let frm = new Form(Size = Size(600, 400))
let gr = frm.CreateGraphics()
gr.FillRectangle(Brushes.Red, Rectangle(Point(0, 0), Point(100, 100)))

Possibly, I also prefer using new for more complicated types and avoid it for simple types or for .NET value types (but I don't think I do this too consistently).


For types which implements IDisposable should be instantiated using new. Otherwise you will get the following compilation warning.

It is recommended that objects that support the IDisposable interface are created using 'new Type(args)' rather than 'Type(args)' to indicate that resources may be owned by the generated value


There is no difference. Both calls will create a a new object with exactly the same IL code.

.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@

To decompile your binary you can use ildasm of the .NET Framework SDK which is in your path when you open a Visual Studio Command Prompt.

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

The option CAVERBAL does print the content of attributes in a human readable form and not binary blobs as usual.

0

精彩评论

暂无评论...
验证码 换一张
取 消