【问题标题】:Error Message: "Cannot convert type 'string?' to 'string' "错误消息:“无法转换类型'字符串?'到‘字符串’”
【发布时间】:2011-10-08 04:10:48
【问题描述】:

我有这个代码:

//Return null if the extension doesn't have the value, returns the value if it does.
private T? getValue<T>(IEnumerable<Extension> extension, string attributeName)
{
    IEnumerable<Extension> ext = extension.Where(e => e.attributeName == attributeName);
    if (ext.Count() > 0)
    {
        return (T)ext.First().Attribute;
    }
    return null;
}

我这样称呼它:

//This works:
retVal.byteValue= getValueFromExtension<byte>(u, "ByteToGet") ?? 0;
//This doesn't work:
getValueFromExtension<string>(u, "Text") ?? "";

我收到编译错误:“错误消息:”无法转换类型'字符串?'到'字符串'"

如何在不创建新方法的情况下有效地实现上面代码中的想法?

我觉得我正在检查它是否为空 ??运算符,因此,如果字符串为空,它将始终设置为空字符串。它是如何处理我对字节和整数的期望的,为什么不处理字符串呢?

仅供参考,上面的 byteValue 是 byte 类型,而不是 byte?。

【问题讨论】:

  • 这段代码可以编译吗?我对 T? 方法的返回类型感到困惑
  • 什么是getValueFromExtension
  • 我不明白为什么你的方法甚至在没有struct 约束的情况下编译。
  • 你为什么会有string?,字符串可以为空。
  • @pikzen:T?Nullable&lt;T&gt; 的简写,它有一个struct type constraint

标签: c# generics nullable


【解决方案1】:

如果它是一个引用类型,你似乎想要null,如果它是一个数字或类似的值类型,你似乎想要0。您可以简单地使用default 关键字从T 获取这样的值。此外,您可能希望将 this 关键字添加到第一个参数,以便将其用作扩展方法。

private T getValue<T>(this IEnumerable<Extension> extension, string attributeName)  
{  
    Extension ext = extension.SingleOrDefault(e => e.attributeName == attributeName);

    if (ext != null)
        return (T)ext.Attribute;
    else
        return default(T);
}  

【讨论】:

  • 如果您需要自定义值类型的默认值,您仍然可以使用类似的内容(注意“byte?”):retVal.byteValue= getValueFromExtension(你,“ByteToGet”)?? 42;但在这种情况下,将默认值作为另一个参数传递给 getValue 方法更有意义
  • @SergGr:很好,没想到。我只能考虑为这个方法添加另一个重载。
  • StackOverflow 太棒了,这里的每一个答案都对我有帮助,大概花了 5 分钟才得到完整的答案。谢谢大家。
【解决方案2】:

T? 表示Nullable&lt;T&gt;,它仅限于结构。字符串不是结构,因此不适合在接受或返回T? 的方法中使用。

不幸的是,如果您想要为值类型和类(例如字符串)返回null,那么您将无法使用单个泛型方法来支持它。您需要按照 Allon 的建议执行并返回 default(T),对于 (非Nullable&lt;T&gt;) 结构,not 为 null,或者定义两个具有不同签名的方法 ,一个用于结构,一个用于类。

private T getValueForClass<T>(IEnumerable<Extension> extension, string attributeName) 
     where T : class 

private T? getValueForStruct<T>(IEnumerable<Extension> extension, string attributeName) 
     where T : struct 

...

var theByte = getValueForStruct<byte>(extensions, "ByteToGet") ?? 0; 
var theString = getValueForClass<string>(extensions, "Text") ?? ""; 

【讨论】:

  • 你的答案很好,我只能接受其中一个作为答案,所以我接受了我实际使用的另一个。
  • @user788402,很好!总是接受对你有用的那个。也可以抛硬币。
【解决方案3】:

你不能有一个可以为空的字符串。 Nullable 的类型参数被约束为值类型,String 为引用类型。您的 getValue 方法返回一个可为空的 T - 您需要将其限制为结构,并为类使用不同的方法:

//Return null if the extension doesn't have the value, returns the value if it does.
private T? getValue<T>(IEnumerable<Extension> extension, string attributeName) where T : struct
{
    IEnumerable<Extension> ext = extension.Where(e => e.attributeName == attributeName);
    if (ext.Count() > 0)
    {
        return (T)ext.First().Attribute;
    }
    return null;
}

//Return null if the extension doesn't have the value, returns the value if it does.
private T getValueObject<T>(IEnumerable<Extension> extension, string attributeName) where T : class
{
    IEnumerable<Extension> ext = extension.Where(e => e.attributeName == attributeName);
    if (ext.Count() > 0)
    {
        return (T)ext.First().Attribute;
    }
    return null;
}

然后

//This works:
getValue<Byte>(u, "ByteToGet") ?? 0;

//This also works:
getValueObject<String>(u, "Text") ?? String.Empty;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    • 2022-08-10
    • 1970-01-01
    相关资源
    最近更新 更多