5

I have .NET application that crashes with NullReferenceException. The funny thing is that the log shows this:

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

The thing that's puzzling me is that the exception happens inside of GetType instead on the line that calls GetType. I've tested following situations.

If I call GetType on an object that is null, the exception happens on a line that's calling GetType, not within GetType. I also tried How can I get a NullReferenceException in this code sample? but strangely I get the exception in Program.Main not within Object.GetType (although in that post it's within GetType).

I also tried concurrently creating objects and calling GetType, but needlesly to say, there is no window in creation of .net objects where GetType throws NullReferenceException. The only thing that crosses my mind right now is that this was maybe behavior of some older .NET implementation.

So any idea how to cause NullReferenceException within GetType, and if you could provide proof of concept code I would be eternally grateful. Thank you for your time.

Community
  • 1
  • 1
Ivan
  • 1,735
  • 1
  • 17
  • 26

2 Answers2

4

One way would be to call the GetType method ("on" a null-reference) with the call instruction rather than the with the callvirt instruction that C# normally uses. This will prevent the pre-method-call runtime null-check from occurring. Instead, the null-reference would be passed to the method, causing the exception to be thrown inside the method itself.

For example, using the InvokeNonVirtual sample provided here, you can do:

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

InvokeNonVirtual(method, args);

This produces a TargetInvocationException with the InnerException being a NullReferenceException having stack-trace:

at System.Object.GetType()
at NonVirtualInvoker(Object )
Ani
  • 111,048
  • 26
  • 262
  • 307
  • Thanks, I didn't know that was possible, I thought that all calls required this != null. Great answer! – Ivan Feb 24 '12 at 05:12
1

I know this post is a little old, but I thought this problem was worth investigating further.

Although the stack trace now doesn't have the additional stack trace line 'at System.Object.GetType()', I managed to replicate most of the error in a small demo application.

I don't really know what is causing it, but I narrowed the suspects down to the DataGrid, ComboBox.SelectedIndex property or the markup extension. If I replace any of these three, the problem goes away, or a different error is shown which is more understanable.

The main window: (a DataGrid with an editable column)

<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>

The code driving this 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; }
        }
    }
}

The markup extension code:

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; }
    }
}

When I run the application, I see this:

Main window with combobox and markup extension on selected index

If I click again on the first column, taking the cell into edit mode, I get this exception:

System.NullReferenceException was unhandled HResult=-2147467261
Message=Object reference not set to an instance of an object.
Source=PresentationFramework StackTrace: at System.Windows.Data.BindingExpressionBase.ConvertValue(Object value, DependencyProperty dp, Exception& e) at System.Windows.Data.BindingExpressionBase.ConvertFallbackValue(Object value, DependencyProperty dp, Object sender) at System.Windows.Data.BindingExpressionBase.get_FallbackValue() at System.Windows.Data.BindingExpressionBase.UseFallbackValue() at System.Windows.Data.BindingExpressionBase.get_Value() at System.Windows.Data.BindingExpressionBase.GetValue(DependencyObject d, DependencyProperty (trimmed)

If I simplify the main window, and remove everything except the ComboBox, and uncomment the line which will create a valid DataContext item, then I get this error:

System.Windows.Markup.XamlParseException occurred
HResult=-2146233087 Message='Set property 'System.Windows.Controls.Primitives.Selector.SelectedIndex' threw an exception.' Line number '19' and line position '39'.
Source=PresentationFramework LineNumber=19 LinePosition=39
StackTrace: at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri) at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri) at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream) at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator) at WpfApplication2.MainWindow.InitializeComponent() in c:\Users\Administrator\Documents\Visual Studio 2012\Projects\WpfApplication2\MainWindow.xaml:line 1 at WpfApplication2.MainWindow..ctor() in c:\Users\Administrator\Documents\Visual Studio 2012\Projects\WpfApplication2\MainWindow.xaml.cs:line 12
InnerException: System.ArgumentException HResult=-2147024809 Message='System.Windows.Data.Binding' is not a valid value for property 'SelectedIndex'. Source=WindowsBase StackTrace: at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal) at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value) at System.Windows.Baml2006.WpfMemberInvoker.SetValue(Object instance, Object value) at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(XamlMember member, Object obj, Object value) at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(Object inst, XamlMember property, Object value) InnerException:

Martin Lottering
  • 1,624
  • 19
  • 31