tags:

views:

128

answers:

5

I'm used to seeing old code like

if (true)
{
    ...
}

where it's intuitively clear that someone was being either lazy or overly cautious when making a change. I ran across this snippet today, and I'm curious whether there's a functional difference between doing type comparison this way:

private static bool logField(Type t, string fieldname)
{
    if (t.ToString() == typeof (Property).ToString())
    {
        ...
    }
    return true;
}

and doing it this way:

private static bool logField(Type t, string fieldname)
{
    if (t == typeof (Property))
    {
        ...
    }
    return true;
}
+3  A: 

I can't think of any good reasons.

In fact, the former will throw if t is null.

Diego Mijelshon
It does take namespaces into account - Type.ToString includes the namespace.
Jon Skeet
@Jon you are correct. I was misled by Reflector (Type.ToString does not include the namespace, but RuntimeType overrides that)
Diego Mijelshon
+6  A: 

I'd say that's generally laziness - but it may not be. For example, you could have two Property types, in the same effective file, but different copies. If typeof(Property) loads it from one file but t is loaded from a different one, your replacement would say they were different but the original code would compare say they were the same.

It's definitely an edge case, and one that you normally want to avoid in the first place... but it's just possible.

Jon Skeet
Very good point about two Property types. If you want to compare types then do it directly, not through string representations. If you want to compare type names (possibly for the reason you give), then do so. Although if code relies on comparing type names I think a comment is in order.
John
I don't know of any case where the DLLs involved would be loaded from multiple locations in the same AppDomain (I have run into that problem, in a different application). Is that what you're referring to when you say "same effective file, but different copies"?
arootbeer
@arootbeer: the way this typically happens is someone loads an assembly via its assembly name, *and*, bizarrely, loads it a second time by its *path*. The CLR reasons that if you are re-loading an already-loaded assembly by its path when you already loaded it by name, then you must be intending to treat those assemblies *and the types in them* as *different*. You can then easily get into the very confusing situation of having two identical types that are not considered identical. Suzanne Cook wrote a bunch of blog entries about this back in the early days, see her blog for details.
Eric Lippert
@Eric Lippert - I ran into this recently in a situation where I was building a plugin system and I had a copy of a DLL (NServiceBus.dll) in two places: the bin folder (it was referenced by the container, correctly) and the plugins folder (it was referenced by a messages dll and I'd copied it there incorrectly). When the loader loaded up the DLLs in the plugins directory, it picked up the 2nd instance of NSB because it was local to where the referencing plugin assembly resided. Then, when it came time to check whether the messages in the plugin were NSB.IMessage, it decided they weren't
arootbeer
cont. - because they were types defined by two separate instances of the DLL. I'd think this might not be as bizarre as explicitly loading the same DLL from the same place, which is why I bring it up.
arootbeer
@arootbeer: Yes, plugins are precisely the situation I was thinking of.
Jon Skeet
A: 

No, getting the type object of 2 instances of the same type will always return a reference to the same type object in memory. This means that performing a reference equality check (==) is sufficient.

Essentially, calling: if (t.ToString() == typeof (Property).ToString())

will call ToString() twice on the same object, where t is the 'Property' type.

Sam
It's good to know that the runtime returns the same reference for each instance of typeof(<Type>) but, as Jon Skeet mentioned, if you load the same type from two different copies of a DLL, the runtime considers them to be different types.
arootbeer
+1  A: 

The first one compares references of Strings, while the second one actually checks to see if t is of the Property type.

The first one will always be "correct" because the two strings refer to the same object, but the second one is the correct way to check if t is of the Property type.

An equivalent and more readable way to do a type check is

if (t is Property)
Duracell
`t is Property` won't work because `t is Type`.
Jerod Houghtelling
A: 

I'd say that the first approach was probably done by someone unfamiliar with C#, not necessary being lazy. The string comparison will work for a majority of the time, except:

  1. If t is null it would throw a null reference exception.
  2. It doesn't take namespaces into consideration.

I would recommend the second case, unless you fall into needing the #2 edge case.

Jerod Houghtelling