27

I need to know how to convert an int to a nullable int. However, I keep getting an error "The binary operator Equal is not defined for the types 'System.Nullable`1[System.Int32]' and 'System.Int32'." Any solution. It needs to be Microsoft SQL Server's nullable int type.

 somevalue = Expression.Constant(something.GetValue(some,null).To<Nullable<System.Int32>> ());

public static T To<T>(this object obj)
    {
        Type t = typeof(T);
        Type u = Nullable.GetUnderlyingType(t);

        if (u != null)
        {
            if (obj == null)
                return default(T);

            return (T)Convert.ChangeType(obj, u);
        }
        else
        {
            return (T)Convert.ChangeType(obj, t);
        }
    }'
Cheran Shunmugavel
  • 8,319
  • 1
  • 33
  • 40
user2582770
  • 391
  • 1
  • 3
  • 10
  • 1
    What's the return type of `something.GetValue`? It looks like you're going to a lot of work for something that should be simpler... – Jon Skeet Aug 02 '13 at 15:07
  • Is the error a compiler error or a run-time error? I have tried to run your method with various input and I have not been able to get any errors. If you get an run-time exception please provide the stack trace. – Martin Liversage Aug 02 '13 at 15:10
  • the return type should be a int?. The problem is that I get pass a int? which is a value from the database and then that function returns an int which I then need to convert back to an int?. The reason for this is because I am trying to make a dynamic query. Also somevalue is a var! not an int? and must always be a var, this cannot change, so I cannot cast like people have suggested. – user2582770 Aug 02 '13 at 15:12

6 Answers6

29

Typically, you convert an int an int? using a cast.

int? myNullable = (int?) 15;
int myInt = (int) myNullable;
Michael Gunter
  • 12,528
  • 1
  • 24
  • 58
26

That To code seems to be you trying to construct a Constant of nullable type when given a value of non-nullable type but that is not at all the right way to go about this. The way you're trying to do this indicates that you have a misunderstanding about how boxed value types work.

That error message indicates that you are constructing a binary operator expression tree node which has as its operands an expression node of nullable int type and an expression node of int type. That's not legal; they have to be both nullable int. What you should be doing is wrapping the non-nullable int expression tree node in a Convert expression tree node which converts it to a nullable int, and then pass that to the binary operator expression tree node constructor.

That is, this is wrong:

var someIntExpr = Expression.Constant(123, typeof(int));
var someNubIntExpr = Expression.Constant(null, typeof(int?));
var badEq = Expression.Equal(someIntExpr, someNubIntExpr);

This is right:

var goodEq = Expression.Equal(Expression.Convert(someIntExpr, typeof(int?)),  someNubIntExpr);

So why is what you're doing wrong?

You have a method To<T> which returns a T. It correctly takes in an int and returns the equivalent int?. So then what? You pass that to Expression.Constant, which boxes the nullable int into a boxed int, and then makes a constant out of that. You believe that there is such a thing as a boxed nullable value type, but there is not! A nullable value type boxes either to a null reference or to a boxed non-nullable value type.

So you could also solve your problem by not doing any of this crazy stuff in the first place. If you have a boxed int in hand, and you need a constant expression tree node of nullable type, just provide the type.

Expression.Constant(someBoxedIntValue, typeof(int?))

Done. So: wrapping up, you have two solutions:

  • If you have a boxed int in hand, pass it and the nullable value type you want to the Constant factory, or
  • if you have an expression node of type int in hand then use the Convert expression node factory, and pass it and the desired type to that.

Both will give you back an expression node of the correct type to be compared to another nullable int.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Hey thanks for the reply, I think you may be right. But I have no idea how to implement this onto my current code. Could you maybe give an example on this var somevalue = Expression.Constant(something.GetValue(some,null).To> ()); Would I just need to change this code only? – user2582770 Aug 03 '13 at 18:37
  • Your a Genius! It Worked! – user2582770 Aug 03 '13 at 18:56
  • 4
    @user2582770: I am not a genius, but I am the guy who wrote a significant fraction of that code. :-) Glad you figured it out. – Eric Lippert Aug 03 '13 at 23:53
  • What is the best way to create a dynamic linq query? I am not too familiar with lamda etc, so I was wondering if you knew any where I can learn to create a dynamic linq query. Thanks – user2582770 Aug 05 '13 at 10:35
  • Still works in here in 2022 using .NET 6. Thanks, Eric! – Tangere Apps Mar 23 '22 at 22:35
  • @user2582770 cant understand how you solve it. Can you post the solucion? – Martin Dec 05 '22 at 23:44
5
int test = 0; // set int

int? num = test; // convert test to a nullable int

num = null; // set num as null
traxs
  • 306
  • 1
  • 5
3
int i = 1;
int? k;
k = i as int?;

Like this you will convert i which is an int to a nullable int ;)

int? is the short version of Nullable<int>.

dotixx
  • 1,490
  • 12
  • 23
3

Does something simpler like this not work?

int i; 
int? temp = int.TryParse(<your value>, out i) ? (int?)i : null;
ToddB
  • 1,464
  • 1
  • 12
  • 27
3

Here you go. A generic string to nullable primitive solution.

int? n = "  99 ".ToNullable<int>(); 

/// <summary>
/// Developed by Taylor Love
/// </summary>
public static class ToNullableStringExtension
{
    /// <summary>
    /// <para>More convenient than using T.TryParse(string, out T). 
    /// Works with primitive types, structs, and enums.
    /// Tries to parse the string to an instance of the type specified.
    /// If the input cannot be parsed, null will be returned.
    /// </para>
    /// <para>
    /// If the value of the caller is null, null will be returned.
    /// So if you have "string s = null;" and then you try "s.ToNullable...",
    /// null will be returned. No null exception will be thrown. 
    /// </para>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="p_self"></param>
    /// <returns></returns>
    public static T? ToNullable<T>(this string p_self) where T : struct
    {
        if (!string.IsNullOrEmpty(p_self))
        {
            var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));
            if (converter.IsValid(p_self)) return (T)converter.ConvertFromString(p_self);
            if (typeof(T).IsEnum) { T t; if (Enum.TryParse<T>(p_self, out t)) return t;}
        }

        return null;
    }

https://github.com/Pangamma/PangammaUtilities-CSharp/tree/master/src/StringExtensions

Pangamma
  • 731
  • 12
  • 28