错误消息:“无法转换类型'字符串?' 'string'“

时间:2011-10-07 19:49:19

标签: c# generics nullable

我有这段代码:

//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") ?? "";

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

如何在不创建新方法的情况下有效地完成上述代码中的想法?

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

FYI,上面的byteValue是字节类型,而不是字节?

3 个答案:

答案 0 :(得分:6)

如果它是引用类型,您似乎想要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);
}  

答案 1 :(得分:3)

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

不幸的是,如果您希望为值类型以及类(例如字符串)返回null,那么您将无法使用单个泛型方法来支持它。您需要按照Allon的建议进行操作并返回default(T) 为(非Nullable<T>)个结构,或者使用不同的签名定义两个方法 ,一个用于结构,一个用于类。

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") ?? ""; 

答案 2 :(得分:2)

你不能拥有可以为空的字符串。 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;