Добавление кода в конструктор с альтернативным синтаксисом класса

type Foo = 
    class
        inherit Bar

        val _stuff : int

        new (stuff : int) = {
            inherit Bar()
            _stuff = stuff
        }
    end

Я хочу добавить этот код в конструктор выше:

if (stuff < 0) then raise (ArgumentOutOfRangeException "Stuff must be positive.")
else ()

Как я могу добиться этого в F#?


person Stringer    schedule 17.11.2009    source источник


Ответы (2)


Вы можете сделать это без каких-либо обходных путей, но размещение начального левого завитка довольно чувствительно (или, может быть, синтаксический анализатор глючит?). Чтобы сначала сделать эффект:

type Foo =
  class
    inherit Bar
    val _stuff : int
    new (stuff : int) = 
      if stuff < 0 then raise (System.ArgumentOutOfRangeException("Stuff must be positive"))
      { 
        inherit Bar() 
        _stuff = stuff 
      }
  end

Чтобы сделать эффект вторым:

type Foo =
  class
    inherit Bar
    val _stuff : int
    new (stuff : int) = 
      { 
        inherit Bar() 
        _stuff = stuff 
      }
      then if stuff < 0 then raise (System.ArgumentOutOfRangeException("Stuff must be positive"))
  end
person kvb    schedule 17.11.2009
comment
Спасибо! Это просто работает. Размещение брекетов действительно придирчиво. - person Stringer; 17.11.2009

Хм, похоже на дыру в грамматике; Я внесу предложение. Вы можете обойти это следующим образом:

type Bar() = class end

type Foo =     
    class        
        inherit Bar        
        val _stuff : int        
        private new (stuff : int, dummyUnused : int) = {            
            inherit Bar()            
            _stuff = stuff        
            }
        new (stuff : int) = 
            Foo(stuff, 0)
            then
                if (stuff < 0) then 
                    raise (System.ArgumentOutOfRangeException 
                             "Stuff must be positive.")
    end

где первый конструктор является фиктивным, единственной целью которого является позволить второму реальному конструктору вызывать его с синтаксисом «другой конструктор, затем побочный эффект».

Однако вы проживете более долгую и счастливую жизнь, если будете использовать

type Foo(_stuff:int) =     
    inherit Bar()
    do
        if (_stuff < 0) then 
            raise (System.ArgumentOutOfRangeException "Stuff must be positive.")

вместо. По возможности используйте классы с первичными конструкторами. («Первичный конструктор» — это конструктор в объявлении класса. В приведенном выше примере аргументы сразу после «type Foo» являются аргументами конструктора, а любые значения let Операторы /do внутри тела класса определяют тело основного конструктора.)

РЕДАКТИРОВАТЬ:

Вот гораздо более простой обходной путь

type Foo =     
    class        
        inherit Bar        
        val _stuff : int        
        new (stuff : int) = 
            let effect = 
                if (stuff < 0) then 
                    raise (System.ArgumentOutOfRangeException 
                            "Stuff must be positive.")
            {            
            inherit Bar()            
            _stuff = stuff        
            }
    end
person Brian    schedule 17.11.2009
comment
Спасибо. Я знаю о первичном ctor, в моем случае мне нужно несколько ctor'ов, так что единственный путь - синтаксис class/end. - person Stringer; 17.11.2009