0x01AA Ответов: 3

Путаница с типажом, допускающих значение null bool в GET-метод свойства


Уважаемые эксперты
У меня есть следующий тестовый код:
public class Person : INotifyPropertyChanged
{
    private bool? valid;

    public bool Valid
    {
        get
        {
            // Test only, expecting an exception in the next statement.
            valid = null;

            // Exception of typecast only shown while debugging *1)
            return ((bool)valid);
        }
        // ....
    }

    // ....
}
*1) приведение
Здесь я ожидаю исключения, и в отладчике это исключение будет показано.
Но при запуске приложения _without_ debugger исключение не будет показано, но оно есть... только не показывается. Кстати, у меня нет никакой попытки / улова, которая скрывает исключение.

Это в отличие от ...
private void buttonNullableBoolTest_Click(object sender, EventArgs e)
{
    bool? nullableBool = null;
    bool testBool= (bool)nullableBool; 
}
... который бросает и показывает также _without_ debugger исключение " System.Исключение InvalidOperationException: объект, допускающий значение null должно иметь значение."

Возникает вопрос: почему приложение не показывает исключение?
Есть идеи, что я не понимаю/неправильно истолковываю на этот раз здесь?
Заранее спасибо.

[Редактировать]
Извините, но теперь, после еще нескольких тестов, я вижу, что мне нужно быть более точным в своем вопросе.

а.) в случае, если я получаю доступ к свойству непосредственно в своем коде, например if (person.Valid)... затем исключение показывается также из отладчика. Так что здесь все как и ожидалось.

Б.) но в случае, если я привязываю это свойство, например, к свойству кнопки Enabled с помощью BindingSource чем приложение не показывает исключение. Похоже на то .NET действительно скрывает исключение в этом случае :(

[Edit2]
Только для информации: привязка непосредственно в коде с buttonBindingTest.DataBindings.Add(new Binding("Enabled", person, "Valid")); делает также работает с ожидаемым поведением (приложение действительно показывает исключение один раз).... но с побочным эффектом эта привязка исчезнет :запутался:

Что я уже пробовал:

Описано в вопросе выше.

Rob Philpott

Просто мысль, но это как-то связано с нитью, на которой ты находишься? Второй пример явно происходит в потоке gui, но NotifyPropertyChange предполагает, что в игре может быть задействован второй поток.

Вот в чем может быть полезен отладчик.

0x01AA

Спасибо за ваш комментарий. Оба теста работают на очень простом тестовом приложении, никаких потоков, ничего особенного.

BillWoodruff

Могу ли я предположить, что иногда это пустая трата времени, чтобы попытаться глубоко проанализировать, как компилятор и время выполнения ведут себя, когда вы пытаетесь заставить.Сеть, чтобы сделать что-то, что не совсем имеет смысл ? Почему бы просто не сделать тип свойства nullable bool и не вернуться к работе?

Philippe Mori

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

0x01AA

Это гораздо хуже, в какой-то ситуации приложение полностью зависает.

0x01AA

Спасибо за ваши отзывы. Вы написали: "... что иногда это пустая трата времени ..."

Да и нет; почему я пытался проанализировать это глубоко?
а) всегда есть шанс - по крайней мере, если я напишу код, - что есть ошибка. И в случае, если такой жук молча пойман, его трудно найти.
б) я не мог поверить, что .Сеть молча ловит исключение, не давая мне возможности узнать об этом.

Наконец - то я нашел это в MSDN.Сеть действительно поддерживает это я буду проинформирован:
Событие: BindingSource.DataError
Описание: возникает, когда связанный с валютой исключение молча обрабатывается BindingSource.
https://msdn.microsoft.com/query/dev11.запрос?идентификатор AppID=Dev11IDEF1&амп;дл=де-де&амп;К=К(Системы.Окна.Формы.Объектом bindingsource.DataError);к(моникер целевой платформы-.NETFramework версии%3Dv4.5);к(DevLang-используется CSharp)&усилитель;РД=истина[^]

3 Ответов

Рейтинг:
9

Richard Deeming

То BindingSource являться причиной. Он подавляет исключения, возникающие при чтении свойств. Вы должны подписаться на BindingComplete событие для просмотра ошибок:
Как обрабатывать ошибки и исключения, возникающие при привязке данных[^]


0x01AA

Да, отлично, большое вам спасибо. Так что в основном моя ошибка заключается в использовании привязки без чтения документации :)

/[Редактировать]
Только для информации: это действительно решает" только " проблему во время процесса привязки, но не тогда, когда исключение происходит после успешной привязки.

Рейтинг:
16

OriginalGriff

Когда я пытаюсь сделать это в своем приложении, построенном для выпуска, я действительно получаю ошибку времени выполнения: "Nullable object must have a value."

Person p = new Person();
Console.WriteLine(p.Valid);

Так что я бы заподозрил, что у вас где - то есть попытка поймать его.
Проверьте свои настройки для отладки:
Меню" отладка"... " исключения..."
В диалоговом окне проверьте столбцы" брошенный "и" необработанный пользователем " и посмотрите, можете ли вы что-нибудь сделать, чтобы получить те же результаты, что и версия выпуска.

[Обновление]

Извините за задержку...Я думал! (И это отнимает у меня некоторое время...)
Я могу дублировать вашу проблему и получить исключение в VS, но не тогда, когда "живу" очень просто, без использования BindingSource, просто переместив действительный доступ геттера в другой поток:
    {
    BackgroundWorker work = new BackgroundWorker();
    work.DoWork += work_DoWork
    work.RunWorkerAsync();
    }

void work_DoWork(object sender, DoWorkEventArgs e)
    {
    Person p = new Person();
    Console.WriteLine(p.Valid);
    }


Это означает, что связанное событие выполняется в другом потоке, который по какой-то причине "проглатывает" исключение.

Так... Я подозреваю, что происходит следующее: привязка данных выполняет код в другом потоке, и когда исключение не обрабатывается, система закрывает поток и не уведомляет вас за пределами отладчика.
Быстрый тест:
    BackgroundWorker work = new BackgroundWorker();
    work.DoWork += work_DoWork;
    work.RunWorkerAsync();
    ...
void work_DoWork(object sender, DoWorkEventArgs e)
    {
    try
        {
        Person p = new Person();
        Console.WriteLine(p.Valid);
        }
    catch (Exception ex)
        {
        File.WriteAllText(@"D:\Temp\aaaaa.txt", DateTime.Now.ToString() + " " + ex.Message);
        }
    }
И исключение регистрируется каждый конец каждый раз.

Что вы с этим делаете? Хороший вопрос: я бы предложил попробовать поймать его, но точно куда вы его положили, я не знаю...


0x01AA

Большое вам спасибо за ваш ответ. Я попробую ваше предложение.
Кстати: это поведение происходит, когда я запускаю отладочный exe-файл из отладчика.

OriginalGriff

Я получаю тот же результат с Debug build EXE и Release build EXE, если я запускаю их без VS loaded вообще.

0x01AA

Извините,я был недостаточно точен и мой вопрос я продлю. В случае, если я непосредственно обращаюсь к свойству в buttonclick, например if (person.Valid) затем я получаю сообщение об ошибке. Но никакое исключение не будет показано, если я свяжу это свойство, например, с кнопкой Enabled

OriginalGriff

Как вы его связываете?

0x01AA

С помощью BindingSource- Я только что обновил вопрос.

Richard Deeming

Необработанные исключения в фоновых потоках приводят к разрушению всего процесса. Так было с .NET 2.0! :)
Исключения в управляемых потоках[^]

0x01AA

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

Н. б: я испытал то же самое для WPF... же "плохого" поведения.

[Редактировать]
И конечно же в следующий раз я ожидаю ответа чего-то более быстрого :смейтесь:

OriginalGriff

Показывает, как часто я позволяю исключениям оставаться необработанными, не так ли? :смеяться:

OriginalGriff

ТЧ! Молодежь сегодня...не хватает терпения на всех.

Я погиб в двух мировых войнах за таких, как ты! Верните национальное страхование, вот что я вам скажу! Пара лет в строительном обществе делают им мир добра!

0x01AA

В то время я охранял границу ... :)

Рейтинг:
1

Karthik_Mahalingam

попробовать это

bool? nullableBool = null;
       bool? testBool = (bool?)nullableBool; // validate the testBool before usage

       // or

       bool? nullableBool = null;
       bool testBool = nullableBool.HasValue ? nullableBool.Value : false;  // if null, it will be assigned as false 


для Nullable Типы использования Свойство HasValue [^]


0x01AA

Спасибо за ваш ответ. Я знаю, как правильно им управлять. Но вопрос в том, почему я не получаю сообщение об исключении для метода getter, когда запускаю приложение без отладчика.

Karthik_Mahalingam

я попытался запустить это без отладки в консольном приложении
я все еще получаю исключение "Nullable object must have a value."

0x01AA

Спасибо за ваши отзывы.

Karthik_Mahalingam

добро пожаловать :)