为什么将ComboBox.SelectedValue设置为null会导致ArgumentNullException?

com*_*cme 7 c# combobox datasource nullreferenceexception winforms

为什么设置SelectedValueComboBox,以null引起ArgumentNullException

仅当ComboBox实际上是表单的一部分时才会发生异常.我可以设置SelectedValue各种没有意义的值或类型,但我无法设置它null.

SelectedValue不是不可能的null.事实上,它的价值 null在我试图将其设置为时null.

在我的真实代码中,这不会发生在构造函数中,而且我并没有明确地将其设置为null.代码正在使用恰好是的变量null.我可以通过null在尝试设置之前检查变量来修复它SelectedValue.但我不明白的是为什么我不能把它设置为一个null值.

代码编辑:DataSource现在包含ValueMembers值实际的项目null

using System.Collections.Generic;
using System.Windows.Forms;

public class Form1 : Form {
    public Form1() {
        var comboBox1 = new ComboBox();
        Controls.Add(comboBox1);
        comboBox1.ValueMember = "Key";
        comboBox1.DisplayMember = "Value";
        comboBox1.DataSource = new List<Record> {
            new Record {Key = "1", Value = "One"}, 
            new Record {Key = null, Value = "null"}
        };
        comboBox1.SelectedItem = null;          // no problem
        comboBox1.SelectedValue = "";           // no problem
        comboBox1.SelectedValue = new object(); // no problem
        comboBox1.SelectedValue = null;         // ArgumentNullException!!
    }
}

public class Record {
    public string Key { get; set; }
    public string Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*son 5

在其中检查属性的实现Reflector看起来像这样:

public object SelectedValue
{
    get
    {
        if ((this.SelectedIndex != -1) && (this.dataManager != null))
        {
            object item = this.dataManager[this.SelectedIndex];
            return this.FilterItemOnProperty(item, this.valueMember.BindingField);
        }
        return null;
    }
    set
    {
        if (this.dataManager != null)
        {
            string bindingField = this.valueMember.BindingField;
            if (string.IsNullOrEmpty(bindingField))
            {
                throw new InvalidOperationException(SR.GetString("ListControlEmptyValueMemberInSettingSelectedValue"));
            }
            PropertyDescriptor property = this.dataManager.GetItemProperties().Find(bindingField, true);
            int num = this.dataManager.Find(property, value, true);
            this.SelectedIndex = num;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以这似乎取决于this.dataManager不是空的.

如果this.dataManager不为null,则setter将Find()使用keyset 调用您要设置的值SelectedValue:

internal int Find(PropertyDescriptor property, object key, bool keepIndex)
{
    if (key == null)
    {
        throw new ArgumentNullException("key");
    }
    if (((property != null) && (this.list is IBindingList)) && ((IBindingList) this.list).SupportsSearching)
    {
        return ((IBindingList) this.list).Find(property, key);
    }
    if (property != null)
    {
        for (int i = 0; i < this.list.Count; i++)
        {
            object obj2 = property.GetValue(this.list[i]);
            if (key.Equals(obj2))
            {
                return i;
            }
        }
    }
    return -1;
}
Run Code Online (Sandbox Code Playgroud)

如果key为null,将抛出异常.

我猜测dataManager当ComboBox插入容器(例如Form)时,它只被设置为非null,这就是为什么当它不在容器中时它不会爆炸的原因.

(实际上,dataManagerControl.DataSource属性设置为非null时,将设置为非null.)

然而,这似乎不太正确,因为你报告了一个NullReferenceException,这明显抛出一个ArgumentNullException.

[编辑]这确实是一个ArgumentNullExeption; OP已相应更新.

  • @ J0e3gan我明白了.这就是代码抛出异常的原因.但_why_就在那里?我已经更新了我的代码,以表明在DataMember属性具有"null"值的项目中完全没问题.我希望能够将SelectedValue设置为"null",因为在这种情况下它是一个有效值. (4认同)

Pau*_*hra 0

也许是因为如果 SelectedValue 的属性 ValueMember 为 Nothing,则 SelectedValue 将在 SelectedItem 上返回 .ToString()。