F # Перестройка конструктора [дубликат]

В то время как , что вызывает NullReferenceExceptions и подходит к avoid / fix , такое исключение было рассмотрено в других ответах, что многие программисты не имеют " t узнал еще, как независимо отлаживать такие исключения во время разработки.

В Visual Studio это обычно легко благодаря Visual Studio Debugger .


Во-первых, убедитесь, что правильная ошибка будет обнаружена - см. . Как разрешить нарушение «Исключение System.NullReferenceException» в VS2010? Примечание1

Затем либо Начать с отладки (F5) , либо Приложить [отладчик VS] к запуску процесса . Иногда может быть полезно использовать Debugger.Break , в котором будет предложено запустить отладчик.

Теперь, когда NullReferenceException выбрано (или необработанно), отладчик остановится ( помните правило, указанное выше?) в строке, на которой произошло исключение. Иногда ошибка может быть легко обнаружена.

Например, в следующей строке единственный код, который может , вызывает исключение, если myString имеет значение null. Это можно проверить, посмотрев окно Watch или выполнив выражения в окне Immediate Window .

var x = myString.Trim();

В более сложных случаях, таких как следуя ниже, вам нужно будет использовать один из методов выше (Watch или Immediate Windows) для проверки выражений, чтобы определить, было ли str1 пустым или если str2 имеет значение null.

var x = str1.Trim() + str2.Trim();

Once , где было выбрано исключение, это обычно тривиально по отношению к разуму назад, чтобы выяснить, где введенное значение null было [неправильно] -

. Найдите время, необходимое для понимания причина исключения. Проверьте нулевые выражения. Проверьте предыдущие выражения, которые могли бы привести к таким нулевым выражениям. Добавьте контрольные точки и, по мере необходимости, пройдите через программу. Используйте отладчик.


1 Если Break on Throws слишком агрессивен и отладчик останавливается на NPE в библиотеке .NET или сторонних разработчиков, Break на User-Unhandled можно использовать для ограничения выловленных исключений. Кроме того, VS2012 представляет Just My Code , который я рекомендую также включить.

Если вы отлаживаете с включенным Just My Code, поведение немного отличается. При включенном Just My Code отладчик игнорирует исключения, связанные с привилегиями обычного языка (CLR) первого шанса, которые выходят за пределы My Code и не проходят через My Code

4
задан kim3er 2 April 2010 в 14:22
поделиться

2 ответа

Я не уверен, что понимаю ваш вопрос; то, что вы написали выше, похоже, должно работать нормально. Если вы спросите, где положить остальную логику конструктора, попробуйте следующее:

type SharedRegistry(useCache) as this =
  inherit PageRegistry(useCache)
  do
    this.ForRequestedType<IAddressRepository>().TheDefaultIsConcreteType<SqlAddressRepository>()
    // etc.
  new() = SharedRegistry(true)

Если вы хотите определить каждый конструктор отдельно, вы также можете это сделать:

type SharedRegistry =
  inherit PageRegistry
  new(useCache) as this = 
    { inherit PageRegistry(useCache) } then
    this.ForRequestedType<IAddressRepository>().TheDefaultIsConcreteType<SqlAddressRepository>()
    // etc.
  new() = SharedRegistry(true)

Или вы можете использовать необязательный аргумент для вашего основного конструктора:

type SharedRegistry(?useCache) as this =
  inherit PageRegistry(defaultArg useCache true)
  do
    this.ForRequestedType<IAddressRepository>().TheDefaultIsConcreteType<SqlAddressRepository>()
    // etc.
5
ответ дан kvb 24 August 2018 в 18:24
поделиться
  • 1
    У меня был "do & quot; и "новый" линии не так. Спасибо за вашу помощь. – kim3er 2 April 2010 в 15:11
  • 2
    Единственная поправка, которую я должен был сделать, - это обернуть методы StructureMap в методах Ignore (), поскольку они возвращают типы. – kim3er 2 April 2010 в 19:12
  • 3
    @ kim3er - Да, если вы вызываете функцию, которая возвращает значение, тогда вам нужно будет ее игнорировать. Вероятно, было бы более идиоматично использовать |> ignore после вызова, чем поставить все это в ignore(...), но методы называются так verbosely, что ни один вариант не выглядит особенно хорошим. – kvb 2 April 2010 в 19:21

Ваш класс C # использует параметры со значением по умолчанию, который немного отличается от перегруженных конструкторов. В любом случае F # поддерживает как перегруженные конструкторы, так и параметры по умолчанию.

Используя значения по умолчанию для параметров, код будет выглядеть так:

type SharedRegistry(?useCache: bool) = 
    do 
      // constructor logic
    inherit PageRegistry(defaultArg useCache true) 

Теперь вы можете создать экземпляр следующим образом:

let r1 = new SharedRegistry() // using the default value
let r2 = new SharedRegistry(false) // specified explicitly
let r3 = new SharedRegistry(useCache=false) // using named parameter

Я верю, что использование именованных параметров немного более элегантно в F #. Способ, которым он работает, заключается в том, что параметр useCache становится option<bool> под обложкой (это может быть проблемой, если вы хотите использовать класс из C #)

Что касается перегруженных конструкторов - ваш код F # должен (см. ответ из kvb ). В общем случае, вероятно, лучше иметь хотя бы один неявный конструктор (так как это позволяет вам автоматически обращаться к параметрам конструктора внутри тела класса, объявлять поля с помощью let и реализовывать логику конструктора с помощью do). Неявный конструктор должен быть тем, который принимает все параметры. В некоторых случаях вы можете сделать это частным, что можно сделать следующим образом:

type SharedRegistry private (useCache: bool) = 
    inherit PageRegistry(useCache) 
    do 
      // constructor logic
    new () = SharedRegistry(true)
4
ответ дан Tomas Petricek 24 August 2018 в 18:24
поделиться
  • 1
    +1 Не совсем то, чем я был, но вы ответили на другой вопрос, который у меня был. – kim3er 2 April 2010 в 15:12
  • 2
    Один незначительный nitpick ... дополнительный new в корпусе конструктора безвреден; как и в большинстве случаев в F #, это не требуется, но может быть использовано явно при желании. – kvb 2 April 2010 в 15:16
  • 3
    @kvb: Ах, я этого не знал. Спасибо за исправление! – Tomas Petricek 2 April 2010 в 15:18
Другие вопросы по тегам:

Похожие вопросы: