I have this code:
//Return nul开发者_如何学Gol 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;
}
I'm calling it like:
//This works:
retVal.byteValue= getValueFromExtension<byte>(u, "ByteToGet") ?? 0;
//This doesn't work:
getValueFromExtension<string>(u, "Text") ?? "";
I get the compile error: "Error Message: "Cannot convert type 'string?' to 'string' "
How can I do effectively the idea in the code above without creating a new method?
I feel like I'm checking if it's null with the ?? operator, so, if the string is null, it will always be set to an empty string. It is handled how I expect for byte and int, why not for string?
FYI, the byteValue above, is of type byte, not byte?.
It seems you want null
if it is a reference type and 0
if it is a number or similar value type. You can simply use the default
keyword to get such a value from T
. Also, you might want to add the this
keyword to the first argument so that it can be used as an extension method.
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);
}
T?
is indicative of a Nullable<T>
, which is something that is limited to structs. A string is not a struct, and therefore is not appropriate to use in a method accepting or returning T?
.
Unfortunately, if you want to return null
for value types as well as classes (such as string), then you would not be able to support that with a single generic method. You would need to do as Allon suggests and return default(T)
, which would not be null for (non-Nullable<T>
) structs, or define two methods with different signatures, one for structs, and one for classes.
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") ?? "";
You can't have a nullable string. The type parameter of Nullable is constrained to be a value type, and String is a reference type. Your getValue method returns a nullable T- you'd need to constrain it to structs, and use a different method for classes:
//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;
}
Then
//This works:
getValue<Byte>(u, "ByteToGet") ?? 0;
//This also works:
getValueObject<String>(u, "Text") ?? String.Empty;
精彩评论