Posted By: eddwo | Sep 4th, 2007 @ 3:18 AM
page 1 of 1
Comments: 22 | Views: 6647
eddwo
eddwo
Wheres my head at?
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?

odujosh
odujosh
Need Microsoft SUX now!
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();
}

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).

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.
odujosh
odujosh
Need Microsoft SUX now!
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.
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.
odujosh
odujosh
Need Microsoft SUX now!
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.
odujosh
odujosh
Need Microsoft SUX now!


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.
littleguru
littleguru
allein, allein,... allein, allein!
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?
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

littleguru
littleguru
allein, allein,... allein, allein!
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.
evildictaitor
evildictaitor
How could you use the adjective "indescribable" truthfully?
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.
littleguru
littleguru
allein, allein,... allein, allein!
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
littleguru
littleguru
allein, allein,... allein, allein!
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);
odujosh
odujosh
Need Microsoft SUX now!
Extensions method inherit so you could implement it for object then use it for any type. Here is a compiled and tested sample.

namespace

Demo

{

public static class Extensions1

{

static public bool IsNull(this object input)

{

return input == null;

}

}

class Program

{

static void Main(string[] args)

{

XmlDocument x = null;

if (x.IsNull())

{

Console.Write("Extension methods inherit");

}

}

}

}

odujosh
odujosh
Need Microsoft SUX now!
I think the implementation of IsNull is no more evil than string.IsNullorEmpty().
bdesmet
bdesmet
Bart De Smet

Actually, you can let the compiler infer the generic type info for you, as illustrated in the following piece of code (C# 3.0):

using System;

class Program
{
   static void Main()
   {
      Bar bar = new Bar();

      /*
      bar.Foo = new Foo();
      bar.Foo.Bar = new Bar();
      bar.Foo.Bar.Foo = new Foo();
      */

      Foo foo = bar.IsNull(b => b.Foo).IsNull(f => f.Bar).IsNull(b => b.Foo);
      Console.WriteLine(foo == null);
   }
}

class Bar
{
   public Foo Foo {get;set;}
}

class Foo
{
   public Bar Bar {get;set;}
}

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

It's not as easy as some kind of proposed ?. operator but it could serve as a workaround, especially when writing query expressions. All it's doing is shortcutting a clumsy nesting of ? : operator uses:

Foo foo = bar != null ? (bar.Foo != null ? (bar.Foo.Bar != null ? (bar.Foo.Bar.Foo != null ? bar.Foo.Bar.Foo : null) : null) : null) : null;

Concerning the ?. operator I do recognize the value as well but I feel it's a bit too late in the Orcas release cycle to design and implement this properly, especially to make it consistent when used in combination with properties and fields, indexers, method invocations, etc, as well as tools functionality such as IntelliSense.

Cheers,
-Bart