"Ternary" operator for different method signatures - c#

I'm looking for an elegant way to choose a method signature (overloaded) and pass an argument based on a conditional. I have an importer that will either produce the most recent file to import, or take an explicit path for the data.
Currently my code looks like this:
if (string.IsNullOrEmpty(arguments.File))
{
importer.StartImport();
}
else
{
importer.StartImport(arguments.File);
}
I would like it to look like this (or conceptually similar):
importer.StartImport(string.IsNullOrEmpty(arguments.File) ? Nothing : arguments.File);
The idea being that a different method signature would be called. A few stipulations:
1) I will not rely on 'null' to indicate an unspecified file (i.e. anything besides null itself).
2) I will not pass the arguments struct to the importer class; that violates the single responsibility principle.
One solution I'm aware of, is having only one StartImport() method that takes a single string, at which point that method resolves the conditional and chooses how to proceed. I'm currently choosing to avoid this solution because it only moves the if-statement from one method to another. I'm asking this question because:
1) I would like to reduce "8 lines" of code to 1.
2) I'm genuinely curious if C# is capable of something like this.

I would like to reduce "8 lines" of code to 1.
I think you're asking the wrong question. It's not how many lines of code you have, it's how clear, maintainable, and debuggable they are. From what you've described, importing from a default location and importing with a known file are semantically different - so I think you're correct in separating them as two different overloads. In fact, you may want to go further and actually name them differently to further clarify the difference.
I'm genuinely curious if C# is capable of something like this.
Sure, we can use all sorts of fancy language tricks to make this more compact ... but I don't think they make the code more clear. For instance:
// build a Action delegate based on the argument...
Action importAction = string.IsNullOrEmpty(arguments.File)
? () => importer.StartImport()
: () => importer.StartImport(arguments.File)
importAction(); // invoke the delegate...
The code above uses a lambda + closure to create a Action delegate of the right type, which is then invoked. But this is hardly more clear ... it's also slightly less efficient, as it requires creating a delegate and then invoking the method through that delegate. In most cases the performance overhead is completely negligible. The real problem here is the use of the closure - it's very easy to misuse code with closures - and it's entirely possible to introduce bugs by using closures incorrectly.

You can't do this using 'strong-typed' C#. Overload resolution is performed at compile time: the compiler will work out the static (compile-time) type of the argument, and resolve based on that. If you want to use one of two different overloads, you have to perform two different calls.
In some cases, you can defer overload resolution until runtime using the dynamic type. However, this has a performance (and clarity!) cost, and won't work in your situation because you need to pass a different number of arguments in the two cases.

Yes, it is possible (using reflection). But I wouldn't recommend it at all because you end up with way more code than you had before. The "8-lines" which you have are quite simple and readable. The "one-liner" using reflection is not. But for completeness sake, here's a one-liner:
importer.GetType().GetMethod("StartImport", string.IsNullOrEmpty(arguments.File) ? new Type[0] : new Type[] { typeof(string) }).Invoke(importer, string.IsNullOrEmpty(arguments.File) ? new object[0] : new object[] { arguments.File) }));

Frankly, I think your code would be a lot more readable and modular if you combined the overloaded methods back into a single method and moved the conditional inside it instead of making the caller pre-validate the input.
importer.StartImport(arguments.File);
void StartImport(string File) {
if (string.isNullOrEmpty(File)) {
...
}
else {
...
}
}
Assuming you call the method from multiple places in your code you don't have the conditional OR ternary expression scattered around violating the DRY principle with this approach.

//one line
if (string.IsNullOrEmpty(arguments.File)) {importer.StartImport();} else{importer.StartImport(arguments.File);}

Related

Wish: Hiding a Deprecated Method with Another Overload Using Default Parameters

Please bear with me, this is not (quite!) a duplicate of any of these SO answers:
Conflicting overloaded methods with optional parameters
Overload Resolution and Optional Parameters in C# 4
Call overload method with default parameters
When trying to "influence" what overload the compiler will choose given conflicts arising from optional parameters, answers in the above posts reference the C# Programming Guide, which indicates the overload resolution (OR) heuristics at play here:
If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call.
Fair enough. My question is, why doesn't (or why can't) the Obsolete attribute (or some other markup) influence the OR decision on judging two candidates to be equally good? For example, consider the following overloads:
[Obsolete(“This method is deprecated.”)]
[EditorBrowsable(EditorBrowsableState.Never)]]
bool foo() { return true; }
bool foo(bool optional = false) { return optional; }
It seems OR should not judge these overloads to be equally good--the non-deprecated overload with an optional parameter should win. If this were the case in this over-simplified example, code previously compiled for foo() would be backwards compatible and happily continue to return true. Future code compiled for this library could also call foo(), but that resolved overload would return false.
Is this a valuable/possible feature we are missing from the language? Or is there any other way to make this wish of mine work? Thanks for any insights,
-Mike
Overload resolution is a very tricky thing to get right, and language designers think long and hard about exactly what the rules should be. The more different considerations and special cases you add, the likely language users are to run into obscure gotchas where it doesn't quite work the way they'd expect. I don't believe adding this new condition to overload resolution would be a valuable addition to the language.
If OR did prefer the method without the ObsoluteAttribute, then the only way to invoke the obsolete method without reflection would be something like this:
((Action)obj.foo)();
And if this were a generic method, there would be no way to call it with an anonymous type parameter. This would definitely be surprising behavior (at least to me).
The ObsoleteAttribute (declared with IsError = false) is a way for you to provide a hint for your consumers to update their code without completely removing the previous capabilities. Typically you want to do this if you plan to remove the feature in a future version. If you want to prohibit them from calling this method entirely, you can either:
Set IsError = true with [Obsolete("This method is deprecated.", true)] so that if the code is re-compiled, it generates an error rather than a warning. It could still be called via reflection.
Remove the deprecated function entirely. It cannot be called via reflection.
It's an interesting question. Still, I prefer it the way it is for the following reasons:
Simplicity
OR depends on method signature compiled to module and it is intuitive at that. Depending on any attributes would change the dependency scope to a wider "thing" and start snowballing - should you consider maybe another attribute? Or attributes on arguments, etc..
Change management
Method signatures & OR are different concern than the deprecation marker attribute. The latter is metadata and if it started to affect OR from one point on, then it would possibly break many existing applications. Especially libraries where deprecation cycle is longer for a reason.
I would be very annoyed if a functionally tested code started to behave different after a soft decision that a certain part of code will be phased out in "undetermined future".
All in all having code like this ...
[Obsolete(“This method is deprecated.”)]
bool foo() { return true; }
bool foo(bool optional = false) { return optional; }
stinks. The compiler will apply an algorithm to select the right method when you call foo() but any developer looking at the code will need to know (and to apply) that algorithm to understand what the code does so maintainability of the code will decrease a lot.
Simply remove the optional in this case as it hurts more than anything else.

Function overloads in C# are they a good idea? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
So i have a situation where i need different amounts of arguments for a function depending on the end result i desire.
I am new to C# and have heard about overloading the function which is not something i have seen before (i started in JavaScript).
But it looks bit dirty, like not a good practice to do even though it does work. Is it generally not a good idea to use overloaded functions, i could probably do an alternative with more work but overloads do make life easier.
It just feels very uncomfortable having more than one method with the same name. Are these considered standard features and acceptable code practice ? Or could it lead to some messy problems in the future that my inexperience does not know about yet and thus i should avoid it ?
Function overloads.
Named actually method overloading. C# does not have a direct distinction to methods which return a value and those that don't. Hence method.
But it looks bit dirty
It is a key component to the language which is a common practice and definitely not frowned upon.
like not a good practice to do even though it does work.
The idea is to provide different variants for a consumer. One consumer may only have X type to use while only Y type is offered. By offering more, the library, and/or instance is more flexible. Plus it lessons failure points by having the consumer convert data to get it into the method.
(i started in JavaScript).
Don't try to program in the style of language which one is accustomed to. Use the specific features of any new language as designed. By trying to do Java in C# or Ruby in C# is foolish. All languages have their design points...program to the language, not to a style of programming.
just feels very uncomfortable having more than one method with the same name.
Coming from a language which is not type safe, that is an understandable reaction. But keep in mind that the compiler is enforcing safety so that widget X is only matched with widget X; it is a true feature and not a gimmick.
Frankly when I see code which does not provide multiple overloads, I view it as either laziness of the developer or some god awful time crunch, hence rushed code.
Don't go overboard...simply provide enough overloads to make the class useable by a majority of consumers.
Or could it lead to some messy problems in the future
If one is not consistent, possibly yes.
So be consistent in the placement of the variables. If an int starts the method, the other method should also start with that same int; if offered. Don't mix the order.
Consider the following class:
public class MyClass
{
public void MyMethod(int a, object b)
{
}
}
If someone else calls your class like this:
new MyClass().MyMethod(1, 1);
And then in a future version of your assembly you add an innocent overload:
public class MyClass
{
public void MyMethod(int a, object b)
{
}
public void MyMethod(object a, int b)
{
}
}
That someone else's code will not compile against the new assembly.
You are correct that method overloading can introduce problems... however it is not always problematic.
Suppose the simple case - you have a method that operates on one Type - T. If you are tempted to add a method overload to handle a second Type U, consider what interfaces and base classes T and U might have in common (including T or U extending one another). If there is a common Type consider making that the argument type at design time (if that's specific enough). If not, then you may need a method overload. A good contrived example might be a method that returns the square of a number. There is no common abstraction for Type's that have an * operator (which you can write your own in C#). So you'd have to make (2) methods to handle an int and a double:
public int SquareMe(int x) { return x * x; }
public double SquareMe(double x) { return x * x; }
If, however, you found yourself wanting to make a method operating on List<T>, IEnumerable<T>, and T[], you may be better off writing the method to accept an IEnumerable<T> (and just calling ToArray() on it immediately to prevent the IEnumerable from expanding multiple times if your code needs it multiple times - if you're just foreach'ing it once, there's no need to expand it) this way you're left with only (1) method to write tests for. Every method, particularly on publicly consumed API's is more to maintain, document, test, automate, etc. Simpler is usually better (but complexity has its place, too). It's difficult to give an algorithm for design of API's (if there was an existing algorithm for such a thing, we could just have the design generated as the output from some hypothetical program, yes?)
When it comes to designing classes and interfaces for public consumption you should be very careful about method overloading (and your entire API, in general - method overloading introducing subtle breaking changes is just one thing to think about - almost any change could be a breaking change). If your API used by everyone, such as Microsoft, all changes to API's have to be very well thought-out and have minimum to 0 breaking changes.
If it's for "internal" use (and you can detect compilation breaks at build time) then if the compiler's happy, method overloading shouldn't be too big of a deal in and of itself. That being said - someone might call a different overload by accident because of what C# will choose. It's probably more important to have explicit method names (Microsoft recommends spelling things out in C#, generally) that intuitively (i.e. subjectively) match the content of what the method does than the concern of overloading.
Like other things, this language features is a trade off between being explicit and implicit and whether or not it's a good idea varies on the situation; method overloading can be both used and abused. In general try to learn the existing practices, patterns and culture of a new language before developing your own style on things so that you can take advantage of everyone's successes and failures before you. Method overloading definitely has its place in C#.
So, you have a situation that would be made easier by a core feature of the language you are using... and you're concerned about that? I wouldn't worry too much.
It might be idea to make an attempt and once you're happy with it take it over to codereview.stackexchange.com to get some feedback.
If the reason for varying signatures is because 'the end result you desire' varies then that's a case for having different functions.
Overloading is helpful when you have a number of optional parameters. If you have five optional parameters it's less obvious what will happen if you specify some but not others. If you create overloads then you can provide different versions of the function with required parameters. Perhaps behind the scenes they can all call a private method with optional parameters, but that remains hidden from public use.
Why not just use an optional parameter?
void Foo (int op = 42)
{
if (x!=42)
//do something
else
}
int x = 33;
Foo();
Foo(x);

Why is Action/Func better than a regular Method in .Net?

I much prefer using an Action or a Func if I need a quick reusable piece of code, however others on my team don't like them or understand them.
At the moment my only real argument is about preference and more up to date code practices, but those are just bad arguments.
Why is it better to do this:
Action<FormView,String> hideControl = (form,name) => {
var button = form.GetControl<Button>(name);
if (button != null)
button.Visible = false;
}
than:
public static void HideControl<T>(this FormView form, string name) where T : Control
{
var button = form.GetControl<Button>(name);
if (button != null)
button.Visible = false;
}
?
Can anyone give me solid concrete arguments/examples?
There are two sides to your question: style and performance.
For code style, using delegates makes things a little messy. There is no function name associated with the body of code (anonymous method), argument types are inferred, and when overused this can lead to large function blocks containing lots of smaller independent chunks of code in delegates. It's not pretty to look at, it can be hard to figure out what the code is actually doing, and it's hard to find what you're looking for.
For performance, delegates introduce an indirection that is not as fast to execute as a plain old method. The difference is small, but when used to excess it could become noticeable.
Any tool has appropriate and excessive uses. It's appropriate to use Action or Func for a callback parameter when you want to pass a callback routine into a function. Using Action or Func as a replacement for declaring functions in general is a misuse, IMO.
The short answer is that, in general, it is not better. I agree with your team mates.
I don't think your question is the right one. Rather than asking why is it better (believe me it is not in most cases), you might ask WHEN is it better.
Now, there are of course times where they are extremely useful, like in LINQ when methods take in a Func, writing a quick lambda is great.
This is far more readable and maintainable:
var myQuery = Customers.Where(x => x.ID == 3).First();
than the alternative:
public bool FilterByID3(Customer cust)
{
return cust.ID == 3;
}
var myQuery = Customers.Where(FilterByID3).First();
In most other cases, it is much more readable/maintainable to use functions.
Why is it better to do this
It's not better. In that case I don't see any advantages in doing this rather than writing a real method. And if you can't either, I don't understand why you're so sure it's better.
Avoid writing long anonymous methods (and by long, I mean more than one or two lines), it just makes the code less readable.
There are however some cases where it can be useful to use an anonymous method: closures. If you need to capture a local variable, then anonymous methods are the way to go. But even then, don't write a long piece of code in it: just call a real method to which you pass the captured variable as a parameter.
In general I agree with the other answerers: Blindly replacing function definitions with Action/Func is not a good thing. Action and Func are not the future of .NET. They are a tool which is very useful but like any tool can be misused.
So if you tend to write code like this
class SomeClass {
Action<...> a1 = (..) => {};
Func<...> f1 = (..) => {};
Action<...> a2 = (..) => {};
...
}
That is certainly not a good thing.
If you do this a lot:
void SomeMethod()
{
Action<..> a = (..) => {};
...
a();
}
then this is actually a good way of encapsulating a little helper method without polluting the class.
To argue your specific case:
If hideControl is only used in a very specific case the private helper method would be preferred. If it is required for a lot of FormViews then the extension method makes more sense. Extension methods are also a tool which can be misused as it can lead to pollution of the public interface for a class. Although you can limit it through the use of namespaces.
I usually go by this guideline:
If you require a helper method which is useful in a lot of places and situations and can be made fairly generic I create an extension method.
If it is a helper method which is required for a specific class but in a several places (methods) in that class then I create a private method.
If it is a helper which I only need in one specific place then I make it a Action/Func inside that method.
Pros
Closures
This does not help your case though.
Super-private methods -- only the defining method can call it.
This is easily countered with the Single Responsibility Principle though. You're likely combining what should be a different class in an entire method.
Callbacks
These can also easily be methods.
Cons
Readability is lessened, in my opinion, because of the excess indentation (I'm not a fan).
Debugging becomes a little harder because your call stack is less intuitive especially when you have multiple Func/Action's defined.
You'll have to over come the cons in your environment.
I'm curious about your "more up-to-date coding practice" argument. Just because you can do this as much as possible doesn't mean you should.

Best practice of using the "out" keyword in C#

I'm trying to formalise the usage of the "out" keyword in c# for a project I'm on, particularly with respect to any public methods. I can't seem to find any best practices out there and would like to know what is good or bad.
Sometimes I'm seeing some methods signatures that look like this:
public decimal CalcSomething(Date start, Date end, out int someOtherNumber){}
At this point, it's just a feeling, this doesn't sit well with me. For some reason, I'd prefer to see:
public Result CalcSomething(Date start, Date end){}
where the result is a type that contains a decimal and the someOtherNumber. I think this makes it easier to read. It allows Result to be extended or have properties added without breaking code. It also means that the caller of this method doesn't have to declare a locally scoped "someOtherNumber" before calling. From usage expectations, not all callers are going to be interested in "someOtherNumber".
As a contrast, the only instances that I can think of right now within the .Net framework where "out" parameters make sense are in methods like TryParse(). These actually make the caller write simpler code, whereby the caller is primarily going to be interested in the out parameter.
int i;
if(int.TryParse("1", i)){
DoSomething(i);
}
I'm thinking that "out" should only be used if the return type is bool and the expected usages are where the "out" parameters will always be of interest to the caller, by design.
Thoughts?
There is a reason that one of the static code analysis (=FxCop) rules points at you when you use out parameters. I'd say: only use out when really needed in interop type scenarios. In all other cases, simply do not use out. But perhaps that's just me?
This is what the .NET Framework Developer's Guide has to say about out parameters:
Avoid using out or reference parameters.
Working with members
that define out or reference
parameters requires that the developer
understand pointers, subtle
differences between value types and
reference types, and initialization
differences between out and reference
parameters.
But if you do use them:
Do place all out parameters after all of the pass-by-value and ref
parameters (excluding parameter
arrays), even if this results in an
inconsistency in parameter ordering
between overloads.
This convention makes the method
signature easier to understand.
Your approach is better than out, because you can "chain" calls that way:
DoSomethingElse(DoThing(a,b).Result);
as opposed to
DoThing(a, out b);
DoSomethingElse(b);
The TryParse methods implemented with "out" was a mistake, IMO. Those would have been very convenient in chains.
There are only very few cases where I would use out. One of them is if your method returns two variables that from an OO point of view do not belong into an object together.
If for example, you want to get the most common word in a text string, and the 42nd word in the text, you could compute both in the same method (having to parse the text only once). But for your application, these informations have no relation to each other: You need the most common word for statistical purposes, but you only need the 42nd word because your customer is a geeky Douglas Adams fan.
Yes, that example is very contrived, but I haven't got a better one...
I just had to add that starting from C# 7, the use of the out keyword makes for very readable code in certain instances, when combined with inline variable declaration. While in general you should rather return a (named) tuple, control flow becomes very concise when a method has a boolean outcome, like:
if (int.TryParse(mightBeCount, out var count)
{
// Successfully parsed count
}
I should also mention, that defining a specific class for those cases where a tuple makes sense, more often than not, is more appropriate. It depends on how many return values there are and what you use them for. I'd say, when more than 3, stick them in a class anyway.
One advantage of out is that the compiler will verify that CalcSomething does in fact assign a value to someOtherNumber. It will not verify that the someOtherNumber field of Result has a value.
Stay away from out. It's there as a low-level convenience. But at a high level, it's an anti-technique.
int? i = Util.TryParseInt32("1");
if(i == null)
return;
DoSomething(i);
If you have even seen and worked with MS
namespace System.Web.Security
MembershipProvider
public abstract MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status);
You will need a bucket. This is an example of a class breaking many design paradigms. Awful!
Just because the language has out parameters doesn't mean they should be used. eg goto
The use of out Looks more like the Dev was either Lazy to create a type or wanted to try a language feature.
Even the completely contrived MostCommonAnd42ndWord example above I would use
List or a new type contrivedresult with 2 properties.
The only good reasons i've seen in the explanations above was in interop scenarios when forced to. Assuming that is valid statement.
You could create a generic tuple class for the purpose of returning multiple values. This seems to be a decent solution but I can't help but feel that you lose a bit of readability by returning such a generic type (Result is no better in that regard).
One important point, though, that james curran also pointed out, is that the compiler enforces an assignment of the value. This is a general pattern I see in C#, that you must state certain things explicitly, for more readable code. Another example of this is the override keyword which you don't have in Java.
If your result is more complex than a single value, you should, if possible, create a result object. The reasons I have to say this?
The entire result is encapsulated. That is, you have a single package that informs the code of the complete result of CalcSomething. Instead of having external code interpret what the decimal return value means, you can name the properties for your previous return value, Your someOtherNumber value, etc.
You can include more complex success indicators. The function call you wrote might throw an exception if end comes before start, but exception throwing is the only way to report errors. Using a result object, you can include a boolean or enumerated "Success" value, with appropriate error reporting.
You can delay the execution of the result until you actually examine the "result" field. That is, the execution of any computing needn't be done until you use the values.

Is extending String class with IsNullOrEmpty confusing?

Everyone knows and love String.IsNullOrEmpty(yourString) method.
I was wondering if it's going to confuse developers or make code better if we extend String class to have method like this:
yourString.IsNullOrEmpty();
Pro:
More readable.
Less typing.
Cons:
Can be confusing because yourString
variable can be null and it looks
like you're executing method on a
null variable.
What do you think?
The same question we can ask about myObject.IsNull() method.
That how I would write it:
public static class StringExt
{
public static bool IsNullOrEmpty(this string text)
{
return string.IsNullOrEmpty(text);
}
public static bool IsNull(this object obj)
{
return obj == null;
}
}
If I'm not mistaken, every answer here decries the fact that the extension method can be called on a null instance, and because of this they do not support believe this is a good idea.
Let me counter their arguments.
I don't believe AT ALL that calling a method on an object that may be null is confusing. The fact is that we only check for nulls in certain locations, and not 100% of the time. That means there is a percentage of time where every method call we make is potentially on a null object. This is understood and acceptable. If it wasn't, we'd be checking null before every single method call.
So, how is it confusing that a particular method call may be happening on a null object? Look at the following code:
var bar = foo.DoSomethingResultingInBar();
Console.Writeline(bar.ToStringOr("[null]"));
Are you confused? You should be. Because here's the implementation of foo:
public Bar DoSomethingResultingInBar()
{
return null; //LOL SUCKER!
}
See? You read the code sample without being confused at all. You understood that, potentially, foo would return a null from that method call and the ToStringOr call on bar would result in a NRE. Did your head spin? Of course not. Its understood that this can happen. Now, that ToStringOr method is not familiar. What do you do in these situations? You either read the docs on the method or examine the code of the call. Here it is:
public static class BarExtensions
{
public static string ToStringOr(this bar, string whenNull)
{
return bar == null ? whenNull ?? "[null]" : bar.ToString();
}
}
Confusing? Of course not. Its obvious that the developer wanted a shorthand method of checking if bar is null and substituting a non-null string for it. Doing this can slash your code significantly and increase readability and code reuse. Of course you could do this in other ways, but this way would be no more confusing than any other. For example:
var bar = foo.DoSomethingResultingInBar();
Console.Writeline(ToStringOr(bar, "[null]"));
When you encounter this code, what do you have to differently than the original version? You still have to examine the code, you still have to determine its behavior when bar is null. You still have to deal with this possibility.
Are extension methods confusing? Only if you don't understand them. And, quite frankly, the same can be said for ANY part of the language, from delegates to lambdas.
I think the root of this problem is what Jon Skeet has mentioned in the list of things he hates in his favorite language (C#): C# should not have imported all extension methods in a whole namespace automatically. This process should have been done more explicitly.
My personal opinion about this specific question is (since we can't do anything about the above fact) to use the extension method if you want. I don't say it won't be confusing, but this fact about extension methods (that can be called on null references) is a global thing and doesn't affect only String.IsNullOrEmpty, so C# devs should get familiar with it.
By the way, it's fortunate that Visual Studio clearly identifies extension methods by (extension) in the IntelliSense tooltip.
I'm personally not a fan of doing this. The biggest problem with extension methods right now is discoverability. Unleses you flat out know all of the methods which exist on a particular type, it's not possible to look at a method call and know that it's an extension method. As such I find it problematic to do anything with an extension method that would not be possible with a normal method call. Otherwise you will end up confusing developers.
A corollary to this problem exist in C++. In several C++ implementations it's possible to call instance methods on NULL pointers as long as you don't touch any fields or virtual methods on the type. I've worked with several pieces of code that do this intentionally and give methods differentt behavior when "this==NULL". It's quite maddening to work with.
This is not to say that I don't like extension methods. Quite the contrary, I enjoy them and use them frequently. But I think there are 2 important rules you should follow when writing them.
Treat the actual method implementation as if it's just another static method because it in fact is. For example throw ArgumentException instead of NullReference exception for a null this
Don't let an extension method perform tricks that a normal instance method couldn't do
EDIT Responding to Mehrdad's comment
The problem with taking advantage of it is that I don't see str.IsNullOrEmpty as having a significant functional advantage over String.IsNullOrEmpty(str). The only advantage I see is that one requires less typing than the other. The same could be said about extension methods in general. But in this case you're additionally altering the way people think about program flow.
If shorter typing is what people really want wouldn't IsNullOrEmpty(str) be a much better option? It's both unambiguous and is the shortest of all. True C# has no support for such a feature today. But imagine if in C# I could say
using SomeNamespace.SomeStaticClass;
The result of doing this is that all methods on SomeStaticClass were now in the global namespace and available for binding. This seems to be what people want, but they're attaching it to an extension method which I'm not a huge fan of.
I really like this approach AS LONG AS the method makes it clear that it is checking the object is null. ThrowIfNull, IsNull, IsNullOrEmpty, etc. It is very readable.
Personally, I wouldn't create an extension that does something that already exists in the framework unless it was a significant improvement in usability. In this instance, I don't think that's the case. Also, if I were to create an extension, I would name it in a way as to reduce confusion, not increase it. Again, I think this case fails that test.
Having said all that, I do have a string extension that tests, not only if the string is null or empty, but also if it only contains whitespace. I call it IsNothing. You can find it here.
It doesn't just look like you're calling a method on a null variable. You /are/ calling a method on a null variable, albeit one implemented through a static extension method. I had no idea extension methods (which I was already leery of) supported that. This even allows you to do crazy things like:
public static int PowerLength(this string obj)
{
return obj == null ? 0 : obj.Length;
}
From where I'm standing now, I would classify any use of an extension method on a null reference under considered harmful.
Let's look at the pro:s and con:s...
More readable.
Yes, slightly, but the improvement in readability is outweighed by the fact that it looks like you are calling an instance method on something that doesn't have to be an instance. In effect it's easier to read, but it's harder to understand, so the improved readability is really just an illusion.
Less typing.
Yes, but that is really not a strong argument. If typing is the main part of your programming, you are just not doing something that is remotely challenging enough for you to evolve as a developer.
Can be confusing because yourString variable can be null and it looks like
you're executing method on a null variable.
True, (as mentioned above).
Yes, it will confuse.
I think that everyone who knows about IsNullOrEmpty() perceives the use of it as quite natural. So your suggested extension method will not add more readability.
Maybe for someone new to .NET this extension method might be easier to deal with, but there is the danger possibility that she/he doesn't understand all facets of extension methods (like that you need to import the namespace and that it can be invoked on null). She/he will might wonder why this extension method does not exist in another project. Anyway: Even if someone is new to .NET the syntax of the IsNullOrEmpty() method might become natural quite fast. Also here the benefits of the extension methods will not outweight the confusion caused by it.
Edit: Tried to rephrase what I wanted to say.
I think extending any object with an "IsNull" type call is a little confusing and should be avoided if possible.
It's arguable that the IsEmptyString method might be useful for the String type, and that because you'd usually combine this with a test for null that the IsNullOrEmpty might be useful, but I'd avoid this too due to the fact that the string type already has a static method that does this and I'm not sure you're saving yourself that much typing (5 characters at most).
Calling a method on a variable that is null usually results in a NullReferenceException. The IsNullOrEmpty()-Method deviates from this behaviour in a way that is not predictable from just looking at the code. Therefore I would advise against using it since it creates confusion and the benefit of saving a couple of characters is minimal.
In general, I'm only ok with extension methods being safe to call on null if they have the word 'null' or something like that in their name. That way, I'm clued in to the fact that they may be safe to call with null. Also, they better document that fact in their XML comment header so I get that info when I mouse-over the call.
When comparing class instance to null using ".IsNull()" is not even shorter than using " == null".
Things change in generic classes when the generic type argument without constraint can be a value type.
In such case comparison with default type is lengthy and I use the extension below:
public static bool IsDefault<T>(this T x)
{
return EqualityComparer<T>.Default.Equals(x, default(T));
}

Categories

Resources