Как System.Object.GetType может генерировать исключение NullRefernceException - PullRequest
5 голосов
/ 24 февраля 2012

У меня есть приложение .NET, которое аварийно завершает работу с NullReferenceException. Самое смешное, что журнал показывает это:

Inner Exception System.NullReferenceException: Object reference not set to an instance of an object.
           at System.Object.GetType()

Меня удивляет то, что исключение происходит внутри GetType, а не в строке, которая вызывает GetType. Я проверил следующие ситуации.

Если я вызываю GetType для объекта, который является нулевым, исключение происходит в строке, которая вызывает GetType, а не внутри GetType. Я также пытался Как я могу получить исключение NullReferenceException в этом примере кода? но странно Я получаю исключение в Program.Main не в Object.GetType (хотя в этом посте это в GetType).

Я также пытался одновременно создавать объекты и вызывать GetType, но стоит сказать, В создании объектов .net нет окна, в котором GetType создает исключение NullReferenceException. Единственное, что приходит мне в голову сейчас, - это, возможно, поведение какой-то более старой реализации .NET.

Так что любая идея, как вызвать исключение NullReferenceException в GetType, и если бы вы могли предоставить подтверждение кода концепции, я был бы бесконечно благодарен Спасибо за ваше время.

Ответы [ 2 ]

3 голосов
/ 24 февраля 2012

Одним из способов будет вызов метода GetType ("on" a null -reference) с инструкцией call, а не с инструкцией callvirt, которую C # обычно использует , Это предотвратит нулевую проверку во время выполнения вызова pre -method. Вместо этого в метод будет передана нулевая ссылка, в результате чего исключение будет внутри самого метода.

Например, используя InvokeNonVirtual образец , предоставленный здесь , вы можете сделать:

var method = typeof(object).GetMethod("GetType");
object[] args = { null };

InvokeNonVirtual(method, args);

Это дает TargetInvocationException с InnerException, являющимся NullReferenceException, имеющим трассировку стека:

at System.Object.GetType()
at NonVirtualInvoker(Object )
0 голосов
/ 20 марта 2013

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

Хотя трассировка стека теперь не имеет дополнительной строки трассировки стека ' в System.Object.GetType () ', мне удалось воспроизвести большую часть ошибок в небольшом демонстрационном приложении.

Я действительно не знаю, что вызывает это, но я сузил подозреваемых до свойства DataGrid, ComboBox.SelectedIndex или расширения разметки. Если я заменю любую из этих трех, проблема исчезнет или появится другая ошибка, которая более понятна.

Главное окно: (сетка данных с редактируемым столбцом)

<Window       x:Class="WpfApplication2.MainWindow"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:src="clr-namespace:WpfApplication2"
                Title="MainWindow" 
               Height="350" 
                Width="525"
                     >
    <DataGrid ItemsSource="{Binding Items}">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Column 1" Width="120">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Description}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox SelectedIndex="{src:ValidatedBinding SelectedIndex}"
                                  VerticalAlignment="Center" HorizontalAlignment="Center" Width="100">
                            <ComboBoxItem>Not Specified</ComboBoxItem>
                            <ComboBoxItem>First</ComboBoxItem>
                            <ComboBoxItem>Second</ComboBoxItem>
                        </ComboBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Window>

Код, управляющий этим окном:

using System.Windows;

namespace WpfApplication2
{
    /// <summary>
    /// The main window.
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            //DataContext = new Item { Description = "Item 1", SelectedIndex = 0 };

            DataContext = new DemoDataContext();
        }
    }

    /// <summary>
    /// An object with 'Items'.
    /// </summary>
    public sealed class DemoDataContext
    {
        readonly Item[] _items = new Item[] {
            new Item { Description = "Item 1", SelectedIndex = 0 },
            new Item { Description = "Item 2", SelectedIndex = 1 },
            new Item { Description = "Item 3", SelectedIndex = 2 },
        };

        public Item[] Items { get { return _items; } }
    }

    /// <summary>
    /// An object with a string and an int property.
    /// </summary>
    public sealed class Item
    {
        int _selectedIndex;
        string _description;

        public string Description
        {
            get { return _description; }
            set { _description = value; }
        }

        public int SelectedIndex
        {
            get { return _selectedIndex; }
            set { _selectedIndex = value; }
        }
    }
}

Код расширения разметки:

using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;

namespace WpfApplication2
{
    /// <summary>
    /// Creates a normal Binding but defaults NotifyOnValidationError and ValidatesOnExceptions to True,
    /// Mode to TwoWay and UpdateSourceTrigger to LostFocus.
    /// </summary>
    [MarkupExtensionReturnType(typeof(Binding))]
    public sealed class ValidatedBinding : MarkupExtension
    {
        public ValidatedBinding(string path)
        {
            Mode = BindingMode.TwoWay;

            UpdateSourceTrigger = UpdateSourceTrigger.LostFocus;

            Path = path;
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            var Target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));

            /* on combo boxes, use an immediate update and validation */
            DependencyProperty DP = Target.TargetProperty as DependencyProperty;
            if (DP != null && DP.OwnerType == typeof(System.Windows.Controls.Primitives.Selector)
                && UpdateSourceTrigger == UpdateSourceTrigger.LostFocus) {
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            }

            return new Binding(Path) {
                Converter = this.Converter,
                ConverterParameter = this.ConverterParameter,
                ElementName = this.ElementName,
                FallbackValue = this.FallbackValue,
                Mode = this.Mode,
                NotifyOnValidationError = true,
                StringFormat = this.StringFormat,
                ValidatesOnExceptions = true,
                UpdateSourceTrigger = this.UpdateSourceTrigger
            };
        }

        public IValueConverter Converter { get; set; }

        public object ConverterParameter { get; set; }

        public string ElementName { get; set; }

        public object FallbackValue { get; set; }

        public BindingMode Mode { get; set; }

        [ConstructorArgument("path")]
        public string Path { get; set; }

        public string StringFormat { get; set; }

        public UpdateSourceTrigger UpdateSourceTrigger { get; set; }
    }
}

Когда я запускаю приложение, я вижу это:

Main window with combobox and markup extension on selected index

Если я снова нажму на первый столбец, переведя ячейку в режим редактирования, я получу следующее исключение:

System.NullReferenceException не обработано HResult = -2147467261
Сообщение = Ссылка на объект не установлена ​​для экземпляра объекта.
Source = PresentationFramework StackTrace: в System.Windows.Data.BindingExpressionBase.ConvertValue (значение объекта, DependencyProperty dp, Exception & e) в System.Windows.Data.BindingExpressionBase.ConvertFallbackValue (Object значение, DependencyProperty dp, Object sender) в System.Windows.Data.BindingExpressionBase.get_FallbackValue () в System.Windows.Data.BindingExpressionBase.UseFallbackValue () в System.Windows.Data.BindingExpressionBase.get_Value () в System.Windows.Data.BindingExpressionBase.GetValue (DependencyObject d, DependencyProperty (обрезается)

Если я упростил главное окно и удалил все, кроме ComboBox, и раскомментировал строку, которая создаст действительный элемент DataContext, тогда я получу эту ошибку:

Произошло исключение System.Windows.Markup.XamlParseException
HResult = -2146233087 Сообщение = 'Установить свойство 'System.Windows.Controls.Primitives.Selector.SelectedIndex' бросил исключение. Номер строки «19» и позиция «39».
Source = PresentationFramework LineNumber = 19 LinePosition = 39
Трассировки стека: at System.Windows.Markup.WpfXamlLoader.Load (XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings настройки, Uri baseUri) в System.Windows.Markup.WpfXamlLoader.LoadBaml (XamlReader xamlReader, логическое skipJournaledProperties, объект rootObject, XamlAccessLevel accessLevel, Uri baseUri) в System.Windows.Markup.XamlReader.LoadBaml (Потоковый поток, ParserContext parserContext, родительский объект, логическое значение closeStream) в System.Windows.Application.LoadComponent (объектный компонент, Uri resourceLocator) в WpfApplication2.MainWindow.InitializeComponent () в c: \ Users \ Администратор \ Documents \ Visual Studio 2012 \ Projects \ WpfApplication2 \ MainWindow.xaml: строка 1 в WpfApplication2.MainWindow..ctor () в c: \ Users \ Администратор \ Documents \ Visual Studio 2012 \ Projects \ WpfApplication2 \ MainWindow.xaml.cs: строка 12
InnerException: System.ArgumentException HResult = -2147024809 Сообщение = 'System.Windows.Data.Binding' не является допустимым значением свойства 'SelectedIndex' . Источник = WindowsBase Трассировки стека: в System.Windows.DependencyObject.SetValueCommon (DependencyProperty dp, Значение объекта, метаданные PropertyMetadata, логическое значение coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType OperationType, Boolean isInternal) в System.Windows.DependencyObject.SetValue (DependencyProperty dp, Object значение) в System.Windows.Baml2006.WpfMemberInvoker.SetValue (экземпляр объекта, Стоимость объекта) в MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue (член XamlMember, Объект объект, значение объекта)в MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue (Object inst, Свойство XamlMember, значение объекта) InnerException:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...