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

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.

Related

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

more advantages or disadvantages to delegate members over classic functions?

class my_class
{
public int add_1(int a, int b) {return a + b;}
public func<int, int, int> add_2 = (a, b) => {return a + b;}
}
add_1 is a function whereas add_2 is a delegate. However in this context delegates can forfill a similar role.
Due to precedent and the design of the language the default choice for C# methods should be functions.
However both approaches have pros and cons so I've produced a list. Are there any more advanteges or disadvantages to either approach?
Advantages to conventional methods.
more conventional
outside users of the function see named parameters - for the add_2 syntax arg_n and a type is generally not enough information.
works better with intellisense - ty Minitech
works with reflection - ty Minitech
works with inheritance - ty Eric Lippert
has a "this" - ty CodeInChaos
lower overheads, speed and memory - ty Minitech and CodeInChaos
don't need to think about public\private in respect to both changing and using the function. - ty CodeInChaos
less dynamic, less is permitted that is not known at compile time - ty CodeInChaos
Advantages to "field of delegate type" methods.
more consistant, not member functions and data members, it's just all just data members.
can outwardly look and behave like a variable.
storing it in a container works well.
multiple classes could use the same function as if it were each ones member function, this would be very generic, concise and have good code reuse.
straightforward to use anywhere, for example as a local function.
presumably works well when passed around with garbage collection.
more dynamic, less must be known at compile time, for example there could be functions that configure the behaviour of objects at run time.
as if encapsulating it's code, can be combined and reworked, msdn.microsoft.com/en-us/library/ms173175%28v=vs.80%29.aspx
outside users of the function see unnamed parameters - sometimes this is helpfull although it would be nice to be able to name them.
can be more compact, in this simple example for example the return could be removed, if there were one parameter the brackets could also be removed.
roll you'r own behaviours like inheritance - ty Eric Lippert
other considerations such as functional, modular, distributed, (code writing, testing or reasoning about code) etc...
Please don't vote to close, thats happened already and it got reopened. It's a valid question even if either you don't think the delegates approach has much practical use given how it conflicts with established coding style or you don't like the advanteges of delegates.
First off, the "high order bit" for me with regards to this design decision would be that I would never do this sort of thing with a public field/method. At the very least I would use a property, and probably not even that.
For private fields, I use this pattern fairly frequently, usually like this:
class C
{
private Func<int, int> ActualFunction = (int y)=>{ ... };
private Func<int, int> Function = ActualFunction.Memoize();
and now I can very easily test the performance characteristics of different memoization strategies without having to change the text of ActualFunction at all.
Another advantage of the "methods are fields of delegate type" strategy is that you can implement code sharing techniques that are different than the ones we've "baked in" to the language. A protected field of delegate type is essentially a virtual method, but more flexible. Derived classes can replace it with whatever they want, and you have emulated a regular virtual method. But you could build custom inheritence mechanisms; if you really like prototype inheritance, for example, you could have a convention that if the field is null, then a method on some prototypical instance is called instead, and so on.
A major disadvantage of the methods-are-fields-of-delegate-type approach is that of course, overloading no longer works. Fields must be unique in name; methods merely must be unique in signature. Also, you don't get generic fields the way that we get generic methods, so method type inference stops working.
The second one, in my opinion, offers absolutely no advantage over the first one. It's much less readable, is probably less efficient (given that Invoke has to be implied) and isn't more concise at all. What's more, if you ever use reflection it won't show up as being a method so if you do that to replace your methods in every class, you might break something that seems like it should work. In Visual Studio, the IntelliSense won't include a description of the method since you can't put XML comments on delegates (at least, not in the same way you would put them on normal methods) and you don't know what they point to anyway, unless it's readonly (but what if the constructor changed it?) and it will show up as a field, not a method, which is confusing.
The only time you should really use lambdas is in methods where closures are required, or when it's offers a significant convenience advantage. Otherwise, you're just decreasing readability (basically the readability of my first paragraph versus the current one) and breaking compatibility with previous versions of C#.
Why you should avoid delegates as methods by default, and what are alternatives:
Learning curve
Using delegates this way will surprise a lot of people. Not everyone can wrap their head around delegates, or why you'd want to swap out functions. There seems to be a learning curve. Once you get past it, delegates seem simple.
Perf and reliability
There's a performance loss to invoking delegates in this manner. This is another reason I would default to traditional method declaration unless it enabled something special in my pattern.
There's also an execution safety issue. Public fields are nullable. If you're passed an instance of a class with a public field you'll have to check that it isn't null before using it. This hurts perf and is kind of lame.
You can work around this by changing all public fields to properties (which is a rule in all .Net coding standards anyhow). Then in the setter throw an ArgumentNullException if someone tries to assign null.
Program design
Even if you can deal with all of this, allowing methods to be mutable at all goes against a lot of the design for static OO and functional programming languages.
In static OO types are always static, and dynamic behavior is enabled through polymorphism. You can know the exact behavior of a type based on its run time type. This is very helpful in debugging an existing program. Allowing your types to be modified at run time harms this.
In both static OO and function programming paradigms, limiting and isolating side-effects is quite helpful, and using fully immutable structures is one of the primary ways to do this. The only point of exposing methods as delegates is to create mutable structures, which has the exact opposite effect.
Alternatives
If you really wanted to go so far as to always use delegates to replace methods, you should be using a language like IronPython or something else built on top of the DLR. Those languages will be tooled and tuned for the paradigm you're trying to implement. Users and maintainers of your code won't be surprised.
That being said, there are uses that justify using delegates as a substitute for methods. You shouldn't consider this option unless you have a compelling reason to do so that overrides these performance, confusion, reliability, and design issues. You should only do so if you're getting something in return.
Uses
For private members, Eric Lippert's answer describes a good use: (Memoization).
You can use it to implement a Strategy Pattern in a function-based manner rather than requiring a class hierarchy. Again, I'd use private members for this...
...Example code:
public class Context
{
private Func<int, int, int> executeStrategy;
public Context(Func<int, int, int> executeStrategy) {
this.executeStrategy = executeStrategy;
}
public int ExecuteStrategy(int a, int b) {
return executeStrategy(a, b);
}
}
I have found a particular case where I think public delegate properties are warrented: To implement a Template Method Pattern with instances instead of derived classes...
...This is particularly useful in automated integration tests where you have a lot of setup/tear down. In such cases it often makes sense to keep state in a class designed to encapsulate the pattern rather than rely on the unit test fixture. This way you can easily support sharing the skeleton of the test suite between fixtures, without relying on (sometimes shoddy) test fixture inheritance. It also might be more amenable to parallelization, depending on the implementation of your tests.
var test = new MyFancyUITest
{
// I usually name these things in a more test specific manner...
Setup = () => { /* ... */ },
TearDown = () => { /* ... */ },
};
test.Execute();
Intellisense Support
outside users of the function see unnamed parameters - sometimes this is helpfull although it would be nice to be able to name them.
Use a named delegate - I believe this will get you at least some Intellisense for the parameters (probably just the names, less likely XML docs - please correct me if I'm wrong):
public class MyClass
{
public delegate int DoSomethingImpl(int foo, int bizBar);
public DoSomethingImpl DoSomething = (x, y) => { return x + y; }
}
I'd avoid delegate properties/fields as method replacements for public methods. For private methods it's a tool, but not one I use very often.
instance delegate fields have a per instance memory cost. Probably a premature optimization for most classes, but still something to keep in mind.
Your code uses a public mutable field, which can be changed at any time. That hurts encapsulation.
If you use the field initializer syntax, you can't access this. So field initializer syntax is mainly useful for static methods.
Makes static analysis much harder, since the implementation of that method isn't known at compile-time.
There are some cases where delegate properties/fields might be useful:
Handlers of some sort. Especially if multi-casting (and thus the event subscription pattern) doesn't make much sense
Assigning something that can't be easily described by a simple method body. Such as a memoized function.
The delegate is runtime generated or at least its value is only decided at runtime
Using a closure over local variables is an alternative to using a method and private fields. I strongly dislike classes with lots of fields, especially if some of these fields are only used by two methods or less. In these situations, using a delegate in a field can be preferable to conventional methods
class MyClassConventional {
int? someValue; // When Mark() is called, remember the value so that we can do something with it in Process(). Not used in any other method.
int X;
void Mark() {
someValue = X;
}
void Process() {
// Do something with someValue.Value
}
}
class MyClassClosure {
int X;
Action Process = null;
void Mark() {
int someValue = X;
Process = () => { // Do something with someValue };
}
}
This question presents a false dichotomy - between functions, and a delegate with an equivalent signature. The main difference is that one of the two you should only use if there are no other choices. Use this in your day to day work, and it will be thrown out of any code review.
The benefits that have been mentioned are far outweighed by the fact that there is almost never a reason to write code that is so obscure; especially when this code makes it look like you don't know how to program C#.
I urge anyone reading this to ignore any of the benefits which have been stated, since they are all overwhelmed by the fact that this is the kind of code that demonstrates that you do not know how to program in C#.
The only exception to that rule is if you have a need for one of the benefits, and that need can't be satisfied in any other way. In that case, you'll need to write more comment than code to explain why you have a good reason to do it. Be prepared to answer as clearly as Eric Lippert did. You'd better be able to explain as well as Eric does that you can't accomplish your requirements and write understandable code at the same time.

"Ternary" operator for different method signatures

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);}

Pros and Cons of using this keyword in c#

In programming you can use the this keyword
this.Textbox
or just
Textbox
What is the best practice?
Some benefits I can see is that using this makes it easier to see in intellisense and makes it easier to understand that it is a property.
Currently I don't use this... I read in some article somewhere that the guy removed all the references, but I don't remember why.
What are the pros and cons of using the this keyword?
Using this systematically will mean that you don't fall into a trap of referring to a local variable when in fact you want a member of this.
The downside: using this will make your code more verbose.
It's really up to personal preference.
The only cons are that it is more typing. Using this (esp. consistently) also precludes, for example, using a parameter when you meant to use a property, e.g. a method f(Textbox textbox) => {textbox = textbox} when you meant to say this.Textbox = textbox. Using it consistently not only makes it impossible to do so but also makes it stand out when you possibly could have.
It's a matter of preference, really. Sometimes you have to use the this keyword, in cases like this:
private string Foo;
public void Bar(string Foo)
{
this.Foo = Foo;
}
Not having the this will result in a bug where the parameter just sets itself to itself. It's less verbose, but some may say it's also less clear (hence preference).
I prefer leaving out this. because it's less typing and less clutter and only use it when necessary because the identifier would be ambiguous otherwise.
As a sidenote I like the way member acces is handled in Cobra. It requires them to be prefixed with a . (or _ for privates). So you'd use .member=parameter. And the first is obviously a member and the second a local variable. An elegant way to remove the ambiguity without becoming verbose.
I've just started to remove this. qualification from a codebase which has turned up a consequence:
Extension methods must have a this. prefix!
Thus, use of extension methods isn't transparent unless this. qualification is used generally.

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