Внедрение типов: при использовании нового? - PullRequest
4 голосов
/ 13 февраля 2011

У меня есть тип, отображающий класс в f # следующим образом:

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

Хорошо, я хочу создать экземпляр этого класса.Я могу сделать так:

let myinstance = MyClass ()

или

let myinstance = new MyClass ()

Какая разница?Могу ли я сделать оба?

Ответы [ 3 ]

8 голосов
/ 13 февраля 2011

Технически, одно отличие состоит в том, что вы должны использовать 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")

Помимо этих двух вещей, нет никаких технических отличий (и, безусловно, нет разницы в сгенерированном IL, когда вы пишете или пропускаетеnew).

Какой из них использовать, когда? Это вопрос стиля.На это не распространяются никакие стандарты кодирования 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 (ноЯ не думаю, что я делаю это слишком последовательно).

2 голосов
/ 13 февраля 2011

Разницы нет. Оба вызова создадут новый объект с точно таким же 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@

Для декомпиляции вашего двоичного файла вы можете использовать ildasm .NET Framework SDK, который находится у вас на пути при открытии командной строки Visual Studio.

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

Опция CAVERBAL печатает содержимое атрибутов в удобочитаемой форме, а не в двоичных двоичных объектах, как обычно.

2 голосов
/ 13 февраля 2011

Для типов, которые реализуют IDisposable, должен создаваться экземпляр с использованием new. В противном случае вы получите следующее предупреждение компиляции.

Рекомендуется, чтобы объекты, поддерживающие интерфейс IDisposable, создавались с использованием 'new Type (args)' вместо 'Type (args)', чтобы указать, что ресурсы могут принадлежать сгенерированному значению

...