Сообщение об ошибке: «Не удалось преобразовать тип« строка? »нанизывать' " - PullRequest
1 голос
/ 07 октября 2011

У меня есть этот код:

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

Я получаю ошибку компиляции: «Сообщение об ошибке:« Не удается преобразовать строку типа »?'to 'string' "

Как эффективно реализовать идею, описанную в приведенном выше коде, без создания нового метода?

Мне кажется, что я проверяю, является ли оно пустым с помощью оператора ??,Итак, если строка имеет значение NULL, она всегда будет установлена ​​на пустую строку. Она обрабатывается так, как я ожидаю для байта и int, а почему не для строки?

FYI, указанное выше byteValue, имеет тип byteне байт?

Ответы [ 3 ]

6 голосов
/ 07 октября 2011

Кажется, вы хотите 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);
}  
3 голосов
/ 07 октября 2011

T? указывает на Nullable<T>, что ограничивается структурами.Строка не является структурой, и поэтому ее нельзя использовать в методе, принимающем или возвращающем T?.

К сожалению, если вы хотите, чтобы вернул null для типов значений, а также классов (таких как строка), вы не сможете поддерживать это с помощью одного универсального метода.Вам нужно будет сделать так, как предлагает Аллон, и вернуть default(T), что not будет нулевым для (не 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 голосов
/ 07 октября 2011

Вы не можете иметь пустую строку.Параметр типа 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;
...