Tech Off Thread

23 posts

The opposite of ??

Back to Forum: Tech Off
  • User profile image
    eddwo

    I understand the ?? operator in C#, it looks useful in some cases, it returns the first operand that is not null, or the default value for the type with value types and null with reference types.

    With ?? you can replace

          int? x = null;
          int y = x != null ? x : -1;

    With

            int? x = null;
            int y = x ?? -1;

    What I seem to need more often is something like the opposite of it.
    An operator which returns null if the first operand is null, or the value of the second operand if the first is not null.

    I'd like something to replace

          Customer customer = null;
          string custname = customer != null ? customer.Name : null;

    With 

          Customer customer = null;
          string custname = customer ~?  customer.Name;



    Wouldn't something like that be a good idea?

  • User profile image
    odujosh

    eddwo wrote:

    string custname = customer ~?  customer.Name;


    Wouldn't something like that be a good idea?



    No. Having an opposite infers there are two values possible: current and the opposite. This can be represented by a bool. Which has two values true and false. Which implements the not operator. (if it is true return false and vice versa)

    Another approach, I would recommend making an interface and implementing it if the need is pervausive.
     
    public interface IInversable<T>
    {

    public T Opposite();
    }

  • User profile image
    Pop Catalin Sever

    I would introduce the a new variant of . operator that works with null references. Something like  .?  ex: name = Customer.?Name, or

    adrees = Customer.?Adress.?City.?Name

    The .? operator should return left side type default value when used on a null object.

    But in any case the only possible value this might add is a little sugar on the sintax expecially where there are lot's of null tests (wich happens to be the case many times when working with object hierachies and there is lot's of drilling operations done on the hierarchy).

  • User profile image
    olmobrutall

    I had exactly the same idea some time ago.

    I choosed ?. over .? cos that way it plays better with other constucts like... :
     
    - Indexers:  dic?[2]
    - Functions: person?.SayHelo() 
    - Delegates: myDelegate?()

    It also has de behavior of 'do nothing' (and returning null if is a function, so is sort circuit like &&).

    My post is in the Linq forum:

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2038330&SiteID=1

    Come on, let's make the idea move and Anders to work a bit more.

    Olmo.

  • User profile image
    odujosh

    I am not sure the concern deserves its own operator. I think functions as showed would provide clear code. Charecter soups is hard to follow.

  • User profile image
    olmobrutall

    For me

    string bossName=null;
    if(Departament!=null)
    {
     Person boss = Departamente.Boss;
     if( boss != null)
       bossName = boss.Name;
    }

    is harder to read than  

    string bossName = Departament?.Boss?.Name

    But also, the second one is an expression, so is possible to be written in a query! while the other one is not.

  • User profile image
    odujosh

    olmobrutall wrote:
    For me

    string bossName=null;
    if(Departament!=null)
    {
     Person boss = Departamente.Boss;
     if( boss != null)
       bossName = boss.Name;
    }

    is harder to read than  

    string bossName = Departament?.Boss?.Name

    But also, the second one is an expression, so is possible to be written in a query! while the other one is not.


    string.IsNullOrEmpty(Department.Boss.Name) ? "": Department.Boss.Name;

    Or you could coalesce at the database level if you store is SQL Server.

    http://www.brettb.com/SQL_Help_Coalesce_Statement.asp

    Linq offer similair functionality: FirstOrDefault Operator or you could also use the string.IsNullOrEmpty in the WHERE clause.

    Hope this helps.

  • User profile image
    eddwo

    string.IsNullOrEmpty(Department.Boss.Name) ? "": Department.Boss.Name;

    That won't work the way you think it will.

    It would throw an exception if the department did not have a boss, since it must evaluate the whole expression before passing it as a parameter.

  • User profile image
    odujosh



    eddwo wrote:
    
    string.IsNullOrEmpty(Department.Boss.Name) ? "": Department.Boss.Name;

    That won't work the way you think it will.

    It would throw an exception if the department did not have a boss, since it must evaluate the whole expression before passing it as a parameter.


    You should always test an object for instantiation before you use it. Writing a generic 'IsNull()' function is pretty easy.

  • User profile image
    littleguru

    odujosh wrote:
    

    eddwo wrote:
    
    string.IsNullOrEmpty(Department.Boss.Name) ? "": Department.Boss.Name;

    That won't work the way you think it will.

    It would throw an exception if the department did not have a boss, since it must evaluate the whole expression before passing it as a parameter.


    You should always test an object for instantiation before you use it. Writing a generic 'IsNull()' function is pretty easy.


    What's the benefit of:

    IsNull(foo.Bar) instead of foo.Bar != null?

  • User profile image
    olmobrutall

    string bossName=null;
    if(!Departament.IsNull())
    {
     Person boss = Departamente.Boss;
     if(!boss.IsNull())
       bossName = boss.Name;
    }

    Something like this? Smiley Could work as an extension method, but anyway is not very handy, isn't it?

    In my post I have an implementation that uses TryXXX extension methods over any type. But because of the limitations of overloading with generic constraints, the name becomes are a bit ugly. (you canĀ“t call all of the methods just 'Try')

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2033762&SiteID=1

  • User profile image
    littleguru

    Yes. Is ugly and a simple:

    if (Department != null)

    is easier to read... at least for me.

    Especially with

    if (!Department.IsNull())

    you have to look at two different positions to understand what you do here. First at the method name and then at the not operator in front of Department.

  • User profile image
    eddwo

    olmobrutall wrote:
    string bossName=null;
    if(!Departament.IsNull())
    {
     Person boss = Departamente.Boss;
     if(!boss.IsNull())
       bossName = boss.Name;
    }


    That wouldn't work either would it?
    If "Department" was in fact null, it wouldn't be there to have the "IsNull()" method called on it.

    I'm not entirely sure how it works with extension methods, but it seems pretty wierd either way.

  • User profile image
    evildictait​or

    eddwo wrote:
    
    olmobrutall wrote:
    string bossName=null;
    if(!Departament.IsNull())
    {
     Person boss = Departamente.Boss;
     if(!boss.IsNull())
       bossName = boss.Name;
    }


    That wouldn't work either would it?
    If "Department" was in fact null, it wouldn't be there to have the "IsNull()" method called on it.

    I'm not entirely sure how it works with extension methods, but it seems pretty wierd either way.


    If Department is the class name and department is a Department object:

    Department department = new Department()

    then you could use a static

    Department.IsNull(department);

    static bool Department.IsNull(Department d){
      return d == null;
    }

    but I agree it's dumb and ugly.

  • User profile image
    littleguru

    eddwo wrote:
    That wouldn't work either would it?
    If "Department" was in fact null, it wouldn't be there to have the "IsNull()" method called on it.

    I'm not entirely sure how it works with extension methods, but it seems pretty wierd either way.
    Works on extension methods because the first argument (marked in C# with the this keyword) can be null. This this keyword is just there to have you not to set the ExtensionMethodAttribute set on the method. The extension method would look like this:

    public static class ObjectExtension
    {
        public static bool IsNull(this object value)
        {
            return value == null;
        }
    }


    Yeah and it is ugly Tongue Out

  • User profile image
    eddwo

    littleguru wrote:
    

    public static class ObjectExtension
    {
        public static bool IsNull(this object value)
        {
            return value == null;
        }
    }



    So with C# 3 you could have something like

    public static class ObjectExtension
    {
       public static R NNV(this object value,Func<T,R> prop)
       {
          return value != default(T) ? prop(value) : default(R);
       }
    }

    and then have an expression like

    Person person = null;
    string bossname = person.NNV(p => p.Department).NNV(d => d.Boss).NNV(b => b.Name);

    Where NNV stands for "NonNullValue"

    (No I don't know my lambda expression syntax very well, and I haven't tested it either)


  • User profile image
    littleguru

    Would look something like this:

    public static class ObjectExtension
    {
        public static TResult IsNull<T, TResult>(this object value, Func<T, TResult> func)
        {
            return value == null ? default(TResult) : func((T)value);
        }
    }

    and is a pain to be used:

    Bar f1 = f.IsNull<Foo, Bar>(x => x.Bar).IsNull<Bar, Foo>(y => y.Foo).IsNull<Foo, Bar>(z => z.Bar);

  • User profile image
    eddwo

    I see. I was assuming it could infer the types of the generic NNV method from the types of the lambda expression, but in actual fact it would have to infer the types of the lambda expression from the specified generic method type parameters.

    Yes that does make it much too long winded to drill down much more than one level in an object graph.

    (Still I'm quite pleased I got it fairly close :0) )

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.