为啥设置 DataSource 时 ComboBox 不抛出异常?

Posted

技术标签:

【中文标题】为啥设置 DataSource 时 ComboBox 不抛出异常?【英文标题】:Why ComboBox doesn't throw an Exception when setting DataSource?为什么设置 DataSource 时 ComboBox 不抛出异常? 【发布时间】:2013-12-28 07:34:30 【问题描述】:

首先是我的代码。我有一堂课:

class Person 
    public int Id  set; get; 
    public string Name  set; get; 
    public Person(int i, string n) Id = i; Name = n;

和一个 ComboBox 对象:

this.comboBox_Persons = new System.Windows.Forms.ComboBox();

在我的代码中的某处:

List<Person> persons = new List<Person>() 
    new Person(5, "John"),
    new Person(8, "Mike")
;
comboBox_Persons.Items.Clear();
comboBox_Persons.DisplayMember = "Name";
comboBox_Persons.ValueMember = "Id";
comboBox_Persons.DataSource = persons;

还有一个静态成员和一个事件处理程序:

public static string test = "";

void comboBox_PersonsSelectedIndexChanged(object sender, EventArgs e)

    test = test + "1";
    string id = (string) comboBox_Persons.SelectedValue;

最后一行是错误的(它来自我的代码的早期版本),应该是:

int id = (int) comboBox_Persons.SelectedValue;

我花了一些时间才意识到我的问题出在这一行。

但我的问题是关于该行的错误版本以及上面的代码。

为什么comboBox_Persons.DataSource被填充时没有抛出异常?

当我的表单准备好时,comboBox_Persons 包含两个项目,它应该显示“John”和“Mike”,但它没有。组合框两次显示类 Person 的类型名称(带有命名空间)。此外,静态字段“test”的值为“11”,这意味着事件处理程序已被调用。但是下一行(转换为字符串)应该抛出异常,但事实并非如此。为什么?接下来,当我单击组合框并更改所选值时,将调用事件处理程序并引发异常(告诉它不能转换为字符串)。

那么,为什么combobox在设置DataSource的时候不抛出异常呢?

为什么组合框显示类型名称而不是定义的属性“名称”?

我想知道为什么这个控件会这样,我在 .NET 文档和 Internet 上都没有找到任何答案。

当我将错误的行更改为正确的版本时,一切正常。

【问题讨论】:

您有问题的代码周围有try/catch 块吗?您没有在示例中显示一个。添加它并查看是否引发了异常。 Winforms 可以根据加载过程的复杂性吞下异常。 有趣!我尝试调试您发布的相同代码,它在 SelectedIndexChanged 中引发异常,但它不会破坏应用程序。看起来异常在某处被捕获??!! 直接运行程序会不会崩溃? IE。在调试器之外。运行程序时会发生某类异常,但在调试时不会发生。您始终可以将异常设置为始终导致中断(甚至是捕获的中断),这至少可以让您看到异常。 @P.Brian.Mackey :不,我没有 try/catch 块中的代码。但是当我添加一个 try/catch 块时,代码会正常运行,因此如果没有该块,就会抛出异常并吞没某处。 @j.i.h. :不,直接运行和在调试器中运行的行为相同。 【参考方案1】:

我在 google 上搜索组合框源代码以了解它是如何实现的以及为什么会隐藏异常,我发现了这个:

http://social.msdn.microsoft.com/Forums/vstudio/en-US/69a0b831-7782-4bd9-b910-25c85f18bceb/visual-studio-doesnt-break-on-unhandled-exception-with-windows-64bit?forum=vsdebug

http://social.msdn.microsoft.com/Forums/vstudio/en-US/8a7006a1-ad86-4aec-9604-d7ccf99ce00b/selectedindexchanged-handler-exception-treated-as-first-chance?forum=vsdebug

有趣的是,如果在 SelectedIndexChanged 事件中添加一行来引发异常,应用程序不会崩溃!!

private void comboBox_persons_SelectedIndexChanged(object sender, EventArgs e)
    
        test = test + "1";
        string id = (string)comboBox_Persons.SelectedValue;
        throw new ApplicationException("Test");
    

显然,这是 64 位计算机的问题,并且有可用的修补程序来解决此问题。如本文所述,Form_Load 事件中易发生异常的代码不会破坏应用程序!组合框 SelectedIndexChanged 事件也是如此。

由于我的机器上没有安装 Win 7 SP1,我无法测试此修补程序。但是,从博客中的 cmets 来看,该修补程序实际上并没有解决所有问题,异常被埋在 64 位机器中。

希望这些信息对您有所帮助!

【讨论】:

感谢您的回答。您提供的链接让我知道更多。我正在使用 Win8 64 位,并且在这个系统上从 Form_Load 抛出异常可以正常工作。我已经在 Win7 SP1 32 位上运行了我的代码(使用组合框),并且尚未引发 SelectedIndexChanged 事件的异常。我无法在其上安装修补程序,因为它不是我的计算机。所以我猜这个问题存在于所有微软系统上。解决像转换为字符串或类似错误这样的错误不是问题,但在我的情况下找到它可能会很耗时。 我知道,静默异常是开发人员最大的敌人!我使用的是 Win7 64 位,即使在明确使用“抛出”之后,我也没有在 Form_Load 中出现异常。当我在项目中更改目标平台时,我看到了不同的行为。我希望他们能尽快找到解决办法。【参考方案2】:

执行以下操作,您的组合框将起作用:

comboBox_Persons.DataSource = persons.ToArray();

这就是我会做的:

Person p = (Person) comboBox_Persons.SelectedItem;

现在你拥有了这个人的所有属性

但是下一行(转换为字符串)应该抛出异常,但它不会。为什么? - 你的值是整数。将整数转换为字符串应该抛出异常。虽然,我相信你那里没有int。 “......它应该显示“John”和“Mike”,但它没有。组合框显示类 Person 的类型名称(带有命名空间)两次......” - 因为你应该做 persons.ToArray() 来获得“John ”和“迈克”。

那么,为什么组合框在设置 DataSource 时不会抛出任何异常? - 因为它只是一个设置,在执行某些操作之前,您可以将任何东西设置为数据源。

改变这个

public static string test = "";....test = test + "1";

到这里

public static int test = 0; ..... test += 1;

祝你好运

【讨论】:

如果您将值转换为不同的类型,它实际上会引发异常!您可以将 int 转换为字符串,但“强制转换”会引发异常。如果你调试上面的代码,你会注意到抛出了“invalid cast”异常,但它并没有中止应用程序。 这是因为他的SelectedValue 不是int 他的代码的方式。一旦你这样做了comboBox_Persons.DataSource = persons.ToArray();,它应该会消失 在您的回答中,您引用了“为什么将整数转换为字符串会引发异常?”。我的评论是对该行的回应。 “转换”到另一种类型总是会引发异常,而转换不会。这种情况下会抛出异常。 @T.S. :你写过“因为你应该做persons.ToArray()来得到'John'和'Mike'”。我认为没有必要,因为当我将转换放在 try/catch 块中或从转换为字符串更改为转换为 int 时,组合框会显示正确的名称。 @Victor。我已经多次使用这种确切的方法,并且从不需要任何尝试/捕获。我不记得为什么,但一项实验表明将 DataSourse 设置为 Array of items 比 List of type 效果更好。同样,这个实验是在 3 到 4 年前完成的,我没有详细说明大多数细节,但我记得的一件事是更喜欢 Array 而不是 List of Type 作为 Datasourse。

以上是关于为啥设置 DataSource 时 ComboBox 不抛出异常?的主要内容,如果未能解决你的问题,请参考以下文章

设置对象的 DataSource 属性时,啥时候使用类型与实例?

为啥 DataSource 不能在 Spring Boot 应用程序中自动装配?

创建在类路径资源[applicationcontext]中定义名为“工厂”的bean时出错。:在设置bean属性“dataSource”时,无法解析对bean“dataSource”的引用;嵌套异常是

通过DataSource为DatagridView绑定数据时为DataGridViewRow.Tag设置值

为啥我的复选框在 dataSource 已同步但传入数据已正确修改后重置?

我已经为 UITableView 的单元格设置了值,但为啥它没有显示?