可空类型 (int?) 不断抛出非可空异常。

3

这是我第一次遇到这样的问题 - 当然这并不意味着什么,但我需要向集体请教,因为虽然我的搜索显示可以解决,但我自己无法解决。

问题在于,如果用户将文本框留空,C#会自动在postback和数据库中输入零。我只想让文本框保持空白。

我有一个类,在其中声明了属性:

private int? _PageNumber = null;

public int? PageNumber
{
    get { return _PageNumber; }
    set { _PageNumber = value; }
}

我的代码文件中有:

if (tbPageNumber.Text != "")
        ia.PageNumber = Convert.ToInt32(tbPageNumber.Text);
    else
        ia.PageNumber = null;

这就是我遇到异常的地方:

CS0037: Cannot convert null to 'int' because it is a non-nullable value type

我想,如果我无法更改类型,也许我可以更改输出。所以我想,也许我可以通过将此放置在文本框的文本属性中来伪造它:

'<%# Eval("PageNumber") == 0 ? null:Eval("PageNumber") %>'

这会抛出CS0019: Operator '==' cannot be applied to operands of type 'object' and 'int'异常。

为什么它如此顽固???


4
这听起来不像是一个异常,而更像是编译时出现的问题。你能否在一个简短而完整的控制台应用程序中重现这个问题,以便将ASP.NET排除在外? - Jon Skeet
CS0037 看起来更像是编译器错误而不是异常。两者之间有很大的区别。 - Albin Sunnanbo
6个回答

5

直截了当地说,ia.PageNumber不可能指的是你提供的定义,因为以下代码不仅编译通过,而且运行正常,并输出设置为空。:

private int? _PageNumber = null;

public int? PageNumber
{
    get { return _PageNumber; }
    set { _PageNumber = value; }
}

if (string.Empty != "")
{
    PageNumber = Convert.ToInt32(string.Empty);
    Console.WriteLine("Setting to value.");
}
else
{
    PageNumber = null;
    Console.WriteLine("Setting to NULL.");
}

关键是 ia.PageNumber 不是 int?或者_PageNumber 不是 int?。为了更加明确我的立场,请看下面的代码:

PageNumber = Convert.ToInt32(" ");
Console.WriteLine("Setting to value {0}.", PageNumber);

抛出了预期的异常:

输入字符串格式不正确。

因此,问题也不可能是填充字符串。为了最终确定我的立场,请查看以下代码:

PageNumber = Convert.ToInt32("");
Console.WriteLine("Setting to value {0}.", PageNumber);

抛出了预期的异常:

输入字符串的格式不正确。

因此,问题也不可能是空字符串。根据 jadarnel27 的评论,您可能正在转换 null,这实际上会成功,以下代码可以进一步证明这一点:

PageNumber = Convert.ToInt32(null);
Console.WriteLine("Setting to value {0}.", PageNumber);

实际上,编译、运行并且没有抛出异常。如预期一样输出字符串Setting to value 0.


如果tbPageNumber.Text为空,则OP的代码在null上调用Convert.ToInt32,这似乎可能是他遇到的问题。他的if检查没有考虑到null,只考虑了空。 - Josh Darnell
@jadarnel27,那并不正确,请看我的编辑。 - Mike Perrenoud
啊。我的错误。我以为我记得转换 null 不起作用,但我从文档中看到是不正确的。 - Josh Darnell
@jadarnel27:CS0037是编译错误,而你指出的潜在错误直到运行时才会发生。 - Cemafor
Michael - 分析得非常好。如果你没有看到,OP 发布了一个答案,说这基本上是用户错误 =) - Josh Darnell
显示剩余2条评论

4
我会尝试以下方法:
if (!string.IsNullOrEmpty(tbPageNumber.Text))
    ia.PageNumber = Convert.ToInt32(tbPageNumber.Text);
else
    ia.PageNumber = null;

一个空字符串和一个null字符串是两个不同的东西,因此一个值为null的字符串可能会在你的代码中被忽略。

2
但问题不在于 null 或空字符串,而在于如何将 null 保存在 int 数据类型中。 - Shaharyar
这个解决方案的问题在于 OP 会得到一个编译器错误。底线是 ia.PageNumber 不是 int? - Mike Perrenoud
@jvanh1,这是不可能的。请看我的回答。 - Mike Perrenoud

3

我为此编写了一个扩展方法,可以帮助我在值类型的情况下进行这些与Web相关的字符串转换:

public static class ExtensionMethods
{
    public static T As<T>(this string input, T fallback = default(T), 
                          IFormatProvider provider = null)
    {
        var type = Nullable.GetUnderlyingType(typeof(T));
        if (type == null)
            type = typeof(T);
        T result;
        try
        {
            result = (T)Convert.ChangeType(input, type, provider);
        }
        catch(Exception)
        {
            result = fallback;
        }
        return result;
    }
}

使用方法如下:

ia.PageNumber = tbPageNumber.Text.As<int>();
ia.PageNumber = tbPageNumber.Text.As<int?>();
ia.PageNumber = tbPageNumber.Text.As<int?>(10);

2

大家好,我可能会因为这个问题被你们“杀死”。

问题在于ia.PageNumber所声明的类位于解决方案中另一个项目中,并由于某种原因没有编译通过,因此有关编译器问题的评论出现了。

这是我使用多个项目的解决方案的第一个,我没有理由去考虑单独编译各个项目(我使用的是Visual Studio 2010)。

好了,我们得到了教训。非常感谢所有做出贡献的人。


0

试试这个:

ia.PageNumber = (int?)null;

编辑:我想错了问题所在...错误提示表明ia.PageNumber是一个int,而不是提供的示例代码中的int?


1
会有什么不同呢? - Rohit Vats

0

CS0019:运算符“==”无法将类型为“object”的操作数和类型为“int”的操作数应用于操作数

尝试将 0 转换成 "0"

'<%# Eval("PageNumber") == "0" ? 0:Eval("PageNumber") %>'

无法将 null 转换为 'int',因为它是一个非可空值类型

pagenumber 中不要使用 null。因为 pagenumber 属性只接受整数值。但是 null 不是整数。所以你会得到上述错误。但是现在我已经将其从 null 改为 0


我不想显示零。 - Risho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接