What's better: id ?? 0 == 0 or id == null || id == 0?
Since I have
public class Foo
{
public int? Id { get; set; }
}
What's better
if ((Id ?? 0) == 0) {}开发者_高级运维
or
if (Id == null || Id == 0)
?
I recommend second one. It is more readable.
And as I have noticed, less people are familiar with ??
operator.
if(Id.GetValueOrDefault() == 0)
Is also an option. In terms of performance, I doubt that there is any real difference, and in any case you would be doing micro-optimization, which is rarely beneficial.
I prefer readability over cleverness (almost) every time, so I definitely go with: if (Id == null || Id == 0)
Even better would be:
if(!Id.HasValue || Id == 0)
{
}
Since this is tagged "performance", here's my general advice on such topics, which I still think is valid here:
- Measure, measure, measure
- Don't micro-optimize unless it's the last thing you can do, and still need to get a few cycles out of a core loop
To expand:
There could very well be things present in your code that makes such micro-optimization tips invalid or non-optimal, so your best option regarding performance is just to measure it. Make sure you measure enough iterations of a loop as measuring that small code 1 time is going to get disturbed by all the other things your machine does invalidating the whole excercise.
As for micro-optimizations, don't worry about it. Pick the one you (and whoever else is going to maintain the code) is most comfortable with, and worry about micro-optimizations if, and when, you actually need to.
Personally I often write the first, ie.
if (o ?? 0 == 0)
or, in the case of strings:
if ((s ?? string.Empty).Length == 0)
However, in terms of readability and "what looks best", this is a bikeshed problem. Go with what you want yourself and feel comfortable with, and move on to bigger issues.
Edit, Ok, I stopped thinking somewhere before that last code example. I combined two different things I do:
- I never leave string properties and fields as
null
unless that is useful - Since 1. I can do
if (PropertyName.Length == 0)
Of course, in that particular example I would use either of the following two:
if (string.IsNullOrEmpty(s))
if (string.IsNullOrWhiteSpace(s))
(only in 4.0, and only if you need to)
If you are using this code one time, it's not quite big difference what to use (but, I'd prefer second one - it's more readable). Otherwise, I'd like to give some name of condition that I verify here. E.g.
public class Foo
{
public int? Id { get; set; }
public bool IsNew
{
get
{
return (Id == null) || (Id == 0);
}
}
}
Now code says what you are verifying. And it's readable as a book
if (IsNew) {}
I reckon that in your case the first example could be fractionally quicker.
I did this both ways in LinqPad
void Main()
{
Foo f = new Foo();
if ((Id ?? 0) == 0) {} // if (f.Id == null || f.Id == 0) {}
}
// Define other methods and classes here
public class Foo
{
public int? Id { get; set; }
}
The IL for if ((Id ?? 0) == 0) {}
is as follows:
IL_0000: newobj UserQuery+Foo..ctor
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: callvirt UserQuery+Foo.get_Id
IL_000C: stloc.1
IL_000D: ldloca.s 01
IL_000F: call System.Nullable<System.Int32>.get_HasValue
IL_0014: brtrue.s IL_0019
IL_0016: ldc.i4.0
IL_0017: br.s IL_0020
IL_0019: ldloca.s 01
IL_001B: call System.Nullable<System.Int32>.GetValueOrDefault
Foo.get_Id:
IL_0000: ldarg.0
IL_0001: ldfld UserQuery+Foo.<Id>k__BackingField
IL_0006: ret
Foo.set_Id:
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld UserQuery+Foo.<Id>k__BackingField
IL_0007: ret
Foo..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret
THE IL for if (f.Id == null || f.Id == 0)
is below - note two calls to get_HasValue
IL_0000: newobj UserQuery+Foo..ctor
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: callvirt UserQuery+Foo.get_Id
IL_000C: stloc.1
IL_000D: ldloca.s 01
IL_000F: call System.Nullable<System.Int32>.get_HasValue
IL_0014: brfalse.s IL_0031
IL_0016: ldloc.0
IL_0017: callvirt UserQuery+Foo.get_Id
IL_001C: stloc.2
IL_001D: ldloca.s 02
IL_001F: call System.Nullable<System.Int32>.GetValueOrDefault
IL_0024: brtrue.s IL_002F
IL_0026: ldloca.s 02
IL_0028: call System.Nullable<System.Int32>.get_HasValue
IL_002D: br.s IL_0030
IL_002F: ldc.i4.0
Foo.get_Id:
IL_0000: ldarg.0
IL_0001: ldfld UserQuery+Foo.<Id>k__BackingField
IL_0006: ret
Foo.set_Id:
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld UserQuery+Foo.<Id>k__BackingField
IL_0007: ret
Foo..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret
Maybe I should get out more!
I do recommand the second one also the code should preferrably like following
if (null == Id || 0 == Id)
精彩评论