zzzprojects / Eval-Expression.NET

C# Eval Expression | Evaluate, Compile, and Execute C# code and expression at runtime.
https://eval-expression.net/
Other
449 stars 86 forks source link

HasValue and also null values #18

Closed lynnmiller closed 6 years ago

lynnmiller commented 6 years ago

My comments and questions are in the code below:

        DateTime? dateTimeA;

        // this works
        dateTimeA = new DateTime(2017, 1, 1);
        string result1 = Eval.Execute<string>("{0}.AddDays(1).ToString()", dateTimeA);
        Console.WriteLine(result1);

        // this is what I want to do ...
        dateTimeA = new DateTime(2017, 1, 1);
        int result2 = dateTimeA.HasValue ? 1 : 0;
        Console.WriteLine(result2);

        // this is also what I want to do, but ...
        dateTimeA = null;
        int result3 = dateTimeA.HasValue ? 1 : 0;
        Console.WriteLine(result3);

        // I can't get it this to work
        dateTimeA = new DateTime(2017, 1, 1);
        int result4 = Eval.Execute<int>("{0}.HasValue ? 1 : 0", dateTimeA);
        Console.WriteLine(result4);

        // And I can't get it this to work
        dateTimeA = null;
        int result5 = Eval.Execute<int>("{0}.HasValue ? 1 : 0", dateTimeA);
        Console.WriteLine(result5);

        Console.ReadKey();
JonathanMagnan commented 6 years ago

Hello @lynnmiller ,

The problem is caused because the dateTimeA variable is a DateTime value, not a nullable DateTime when assigned.

DateTime? dateTimeA;
dateTimeA = new DateTime(2017, 1, 1);
var type = dateTimeA.GetType(); // = DateTime ... not DateTime?

Obviously, HasValue doesn't exists on a DateTime which cause the error.

There is two way to solve this issue

Compile + Execute

When compiling, you can specify the type.

// COMPILE + EXECUTE
DateTime? dateTimeA;

var compiled = Eval.Compile<Func<DateTime?, int>>("dateTimeA.HasValue ? 1 : 0", "dateTimeA");

dateTimeA = new DateTime(2017, 1, 1);
int r5 = compiled(dateTimeA);

dateTimeA = null;
int r6 = compiled(dateTimeA);

Class + Execute

Don't use a nullable variable anymore, add the value in a field or property in a class instead. In this way, the true type will be able to be found.

public class EntityWithNullable
{
    public DateTime? dateTimeA;
}

var entityWithNullable = new EntityWithNullable() {dateTimeA = new DateTime(2017, 1, 1)};
int r3 = Eval.Execute<int>("dateTimeA.HasValue ? 1 : 0", entityWithNullable);

entityWithNullable.dateTimeA = null;
int r4 = Eval.Execute<int>("dateTimeA.HasValue ? 1 : 0", entityWithNullable);

Let me know if that help you to solve your issue.

Best Regards,

Jonathan

JonathanMagnan commented 6 years ago

Hello @lynnmiller ,

I will close this issue but if you have more question, feel free to reopen it.

Best Regards,

Jonathan