问题
So, I really enjoy using extension methods.. maybe a bit too much. So, I'm going to ask about my latest enjoyment to ensure that I'm not going too far.
Scenario is that we have a Guid?
variable that gets passed in. If the variable is null or Guid.Empty
, then we want to use a different Guid. So, I wrote an extension method to make it read like English:
internal static Guid OrIfEmpty(this Guid? guid, Guid other)
{
if (!guid.HasValue || guid.Value == Guid.Empty)
{
return other;
}
return guid.Value;
}
This automatically implies that a "null this" will not throw an exception. For instance, this will work:
((Guid?)null).OrIfEmpty(other);
This is not possible without using extension methods, and in my opinion can be quite misleading. However, it's just so concise and clean! So, what do you think? Is this an acceptable thing to do or could it be too confusing to other programmers?
Also, I'm sure there will be other scenarios where I do things like this and checking this
for null, but this is the best example I have right now.
Note: I'm not really asking about this Guid?
business in particular. I'm asking more about the overall pattern implemented (having an extension method where the this
can be null
)
回答1:
This is not possible without using extension methods
Sure it is, just make is a regular static method call (which is all extension methods are):
in my opinion can be quite misleading
I agree, since it looks like you're calling an instance method on a null
instance. It could be worse:
string s = null;
string n = s.OrIfEmpty("empty");
At first glance this looks like an obvious NullReferenceException
waiting to happen, but it compiles and works as designed.
Since your question is really just soliciting opinions, there's not one right answer, but I certainly would be cautious and document the extension method to indicate that the this
parameter could be null
. Or (as @quezalcoatl implies) rename it to be more explicit that it supports null
values:
internal static Guid OrIfNullOrEmpty(this Guid? guid, Guid other)
回答2:
I personally I think there will be much more developers that understand better and faster (so in the end means the code is cleaner):
if (!guid.HasValue || guid.Value == Guid.Empty)
{
return other;
}
Rather than:
((Guid?)null).OrIfEmpty(other);
So it depends if you're coding for yourself or what you write could be supported by others. Personally I don't think the value added is worth the "weirdness" :)
回答3:
In general, an extension method should check for null values. After all, an extension method is nothing more than a static method with some syntactic sugar added so that the compiler can treat it like an instance method.
For example, if you have this:
public static class MyExtensions
{
public static IEnumerable<TSource> Frob<TSource>(this TSource source)
{
// do stuff here
}
}
You can then call it two different ways:
var foo = new List<int>();
var bar = foo.Frob(); // called like an instance method
var barby = MyExtensions.Frob(foo); // called like a static method
Whereas with a normal instance method you can assume that this
is not null, you can't make that assumption with an extension method.
回答4:
I do not see any problem with that. Just recall the
string.IsNullOrEmptyOrWhitespace
that comes from stdlib.
In general, it depends on what will you do on that null case. If you use the function in a normal way, and if the function behaves normally with that special case - all's ok. But if your function gets into debug mode and starts reconfiguring the system, well, you've crossed the Principle-of-Least-Astonishment and that is not good
-- note: as @JeppeStigNielsen accurately pointed out, the INOEOW is not an extension method in the current version of .Net. I am sure that I had it a few times as extension method, but most probably it was on some CTP version or maybe it was custom addon for old versions of .Net where it didn't exist at all. Sorry for the confusion! Nevertheless, "it's all about proper naming" stil holds! :)
回答5:
I think this is OK. Note that the example with Nullable<Guid>
is not that bad, since so-called null
of type Nullable<Guid>
is a real and existing value of Nullable<Guid>
, not "nothing".
That's why you can also use instance methods on this kind of "null", as in
Guid? g = null;
g.GetValueOrDefault(); // OK; real instance method
Using this with a reference type is even more "strange":
internal static string OrIfEmpty(this string str, string other)
{
return string.IsNullOrEmpty(str) ? other : str;
}
Because then you can call it on a "real" null:
string s = null;
s.OrIfEmpty("unspecified"); // OK; s is a true null reference
来源:https://stackoverflow.com/questions/14565881/is-null-this-an-acceptable-use-of-extension-methods