views:

220

answers:

3

I'm trying to convert an XElement to either null or whatever type T is supplied.

Here's what I have so far:

public static T? ConvertToNullable<T>(this XElement element) where T : IConvertible
{
    if (element.IsNill())
        return null;
    else
        return (T)element;
}

Error:

The type T must be a non-nullable value type in order to use it as parameter T in the generic type or method System.Nullable<T>

Can this be done or do I have to write a separate extension for bool, byte, int, long, double, decimal, etc.?

Edit

I shouldn't have been using generics for this at all. See my answer below.

+2  A: 

Use where T : struct so that your method is restricted to value types (which Nullable only makes sense for).

Matt Hamilton
Thanks but doesn't work. I get "Cannot convert `XElement` to `T`".
DanM
Perhaps "where T : struct, IConvertible" then? Use both clauses?
Matt Hamilton
@Matt, Thanks for the ideas, but I think I've got it figured out now (see edit and answer). I can just as easily do the cast where I call the extension method, which I think is more clear anyway.
DanM
+3  A: 

I'm not sure what you're trying to do here... the only non-nullable types are value types, and XElement is a reference type. So it doesn't make sense to cast it to a Nullable<T>...

Thomas Levesque
true, even if you can get past the generic error it will blow up on the cast.
Nathan W
An XElement has explicit casts for all the value types and Nullable<valueType> types. See http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.op_explicit.aspx. So, I thought I could tap into this somehow with a generic. Are you saying that's impossible?
DanM
@Dan: That's many, but not all of the value types. A generic method has to be a common valid action for all types it can be instantiated with, meaning XElement would have to provide a single generic cast method that you could call. This is the same reason why XElement uses some 20 different methods for its explicit casts instead of providing a generic one.
280Z28
Thanks for the help, guys. I think I've got it now (see my edit and answer).
DanM
+1  A: 

Okay, I got it now. I didn't need to use generics at all. I can just leave it as an XElement and do the cast where I call the extension method.

So, my revised code looks like this:

public static XElement NullIfNill(this XElement element)
{
    if (element.IsNill())
        return null;
    else
        return element;
}

Usage example:

var results =
    from
        p in participants.Elements()
    join
        co in conditionOrders.Elements()
        on (int?)p.Element(NS + "conditionOrderId").NullIfNill() equals (int)co.Element(NS + "id")
DanM