Related
I want to automatically remove all explicit types and exchange them with the var keyword in a big solution, e.g. instead of
int a = 1;
I want to have:
var a = 1;
This is just cosmetics, the code in the solution works perfectly fine, I just want to have things consistent, as I started out using explicit types, but later on used var-keywords.
I'm guessing I would have to write some sort of code parser - sounds a little cumbersome. Does anybody know an easy solution to this?
Cheers,
Chris
This isn't an answer per se, but it's too long for a comment.
You should strongly consider not doing this. There's no stylistic concern with mixing explicit and inferential typing (you should infer types when you need to, either when using anonymous types or when it makes the code easier to read), and there are plenty of potential issues you'll encounter with this:
Declarations without assignment are ineligible
Declarations that are assigned to null are ineligible
Declarations that are of a supertype but initialized to an instance of a subtype (or compatible but different type) would change their meaning.
I.E.
object foo = "test";
...
foo = 2;
Obviously, this is a simple (and unlikely) example, but changing foo from object to var would result in foo being typed as a string instead of object, and would change the semantics of the code (it wouldn't even compile in this case, but you could easily run into more difficult to find scenarios where it changes overload resolution but doesn't produce a compile-time error).
In other words, don't do this, please.
Firstly, this is probably not such a good idea. There is no advantage to var over int; many declarations will be almost as simple.
But if you must...
A partly manual solution is to turn ReSharper's "Use var" hint into a warning and get it to fix them all up. I don't know if ReSharper will do it en masse, but I often rifle through a badly-done piece of third-party code with a rapid sequence of Alt+PgDn, Alt+Enter.
This has the significant advantage that ReSharper respects the semantics of your code. It won't replace types indiscriminately, and I'm pretty sure it will only make changes that don't affect the meaning of your program. E.g.: It won't replace object o = "hello"; (I think; I'm not in front of VS to check this).
Look into Lex & Yacc. You could combine that with a perl or awk script to mechanically edit your source.
You could also do this in emacs, using CEDET. It parses code modules and produces a table of its code analysis.
In either case you will need to come up with an analysis of the code that describes... class declarations (class name, parent types, start and end points), method declarations (similar), variable declarations, and so on. Then you will write some code (perl, awk, powershell, elisp, whatever) that walks the table, and does the replace on each appropriate variable declaration.
I'd be wary of doing this in an automated fashion. There are places where this may actually change the semantics of the program or introduce errors. For example,
IEnumerable<string> list = MethodThatReturnsListType();
or
string foo = null;
if (!dict.TryGetValue( "bar", out foo ))
{
foo = "default";
}
Since these aren't errors, I would simply replace them as you touch the code for other reasons. That way you can inspect the surrounding code and make sure you aren't changing the semantics and avoid introducing errors that need to be fixed.
What's about search/replace in Visual Studio IDE
For example search vor 'int ' and replace it with 'var '.
In C#, the following code doesn't compile:
class Foo {
public string Foo;
}
The question is: why?
More exactly, I understand that this doesn't compile because (I quote):
member names cannot be the same as their enclosing type
Ok, fine. I understand that, I won't do it again, I promise.
But I really don't understand why the compiler refuses to take any field having the same name as an enclosing type. What is the underlying issue that prevents me to do that?
Strictly speaking, this is a limitation imposed by C#, most likely for convenience of syntax. A constructor has a method body, but its member entry in IL is denoted as ".ctor" and it has slightly different metadata than a normal method (In the Reflection classes, ConstructorInfo derives from MethodBase, not MethodInfo.) I don't believe there's a .NET limitation that prevents creating a member (or even a method) with the same name as the outer type, though I haven't tried it.
I was curious, so I confirmed it's not a .NET limitation. Create the following class in VB:
Public Class Class1
Public Sub Class1()
End Sub
End Class
In C#, you reference it as:
var class1 = new Class1();
class1.Class1();
Because Foo is reserved as the name of the constructor.
So if your code was allowed - what would you call the constructor?
Even if it was possible to do this by treating the constructor as a special case and introducing new rules into method / member binding - would it be a good idea? It would inevitably lead to confusion at some point.
Because the member name clashes with the name of the class's constructor?
There is a right way to do it and a wrong way to do it.
Why Doesn't C# allow it?
Because it does not reason to do so. Why would you want to create such confusion in your life.
I think the CLR allows it, as another post proves with a vb.net example and it should not be restricted, but I would not want to create an application based on the same rules that the CLR operates in. The abstraction makes code more clear. I think the argument works on the same level as multiple inheritance. Yes it can be done in some languages, but it causes confusion. My answer therefore would be to reduce ambiguity and confusion and is based in the c# parser/compiler. A design choice by the C# team.
I am a PHP web programmer who is trying to learn C#.
I would like to know why C# requires me to specify the data type when creating a variable.
Class classInstance = new Class();
Why do we need to know the data type before a class instance?
As others have said, C# is static/strongly-typed. But I take your question more to be "Why would you want C# to be static/strongly-typed like this? What advantages does this have over dynamic languages?"
With that in mind, there are lots of good reasons:
Stability Certain kinds of errors are now caught automatically by the compiler, before the code ever makes it anywhere close to production.
Readability/Maintainability You are now providing more information about how the code is supposed to work to future developers who read it. You add information that a specific variable is intended to hold a certain kind of value, and that helps programmers reason about what the purpose of that variable is.
This is probably why, for example, Microsoft's style guidelines recommended that VB6 programmers put a type prefix with variable names, but that VB.Net programmers do not.
Performance This is the weakest reason, but late-binding/duck typing can be slower. In the end, a variable refers to memory that is structured in some specific way. Without strong types, the program will have to do extra type verification or conversion behind the scenes at runtime as you use memory that is structured one way physically as if it were structured in another way logically.
I hesitate to include this point, because ultimately you often have to do those conversions in a strongly typed language as well. It's just that the strongly typed language leaves the exact timing and extent of the conversion to the programmer, and does no extra work unless it needs to be done. It also allows the programmer to force a more advantageous data type. But these really are attributes of the programmer, rather than the platform.
That would itself be a weak reason to omit the point, except that a good dynamic language will often make better choices than the programmer. This means a dynamic language can help many programmers write faster programs. Still, for good programmers, strongly-typed languages have the potential to be faster.
Better Dev Tools If your IDE knows what type a variable is expected to be, it can give you additional help about what kinds of things that variable can do. This is much harder for the IDE to do if it has to infer the type for you. And if you get more help with the minutia of an API from the IDE, then you as a developer will be able to get your head around a larger, richer API, and get there faster.
Or perhaps you were just wondering why you have to specify the class name twice for the same variable on the same line? The answer is two-fold:
Often you don't. In C# 3.0 and later you can use the var keyword instead of the type name in many cases. Variables created this way are still statically typed, but the type is now inferred for you by the compiler.
Thanks to inheritance and interfaces sometimes the type on the left-hand side doesn't match the type on the right hand side.
It's simply how the language was designed. C# is a C-style language and follows in the pattern of having types on the left.
In C# 3.0 and up you can kind of get around this in many cases with local type inference.
var variable = new SomeClass();
But at the same time you could also argue that you are still declaring a type on the LHS. Just that you want the compiler to pick it for you.
EDIT
Please read this in the context of the users original question
why do we need [class name] before a variable name?
I wanted to comment on several other answers in this thread. A lot of people are giving "C# is statically type" as an answer. While the statement is true (C# is statically typed), it is almost completely unrelated to the question. Static typing does not necessitate a type name being to the left of the variable name. Sure it can help but that is a language designer choice not a necessary feature of static typed languages.
These is easily provable by considering other statically typed languages such as F#. Types in F# appear on the right of a variable name and very often can be altogether ommitted. There are also several counter examples. PowerShell for instance is extremely dynamic and puts all of its type, if included, on the left.
One of the main reasons is that you can specify different types as long as the type on the left hand side of the assignment is a parent type of the type on the left (or an interface that is implemented on that type).
For example given the following types:
class Foo { }
class Bar : Foo { }
interface IBaz { }
class Baz : IBaz { }
C# allows you to do this:
Foo f = new Bar();
IBaz b = new Baz();
Yes, in most cases the compiler could infer the type of the variable from the assignment (like with the var keyword) but it doesn't for the reason I have shown above.
Edit: As a point of order - while C# is strongly-typed the important distinction (as far as this discussion is concerned) is that it is in fact also a statically-typed language. In other words the C# compiler does static type checking at compilation time.
C# is a statically-typed, strongly-typed language like C or C++. In these languages all variables must be declared to be of a specific type.
Ultimately because Anders Hejlsberg said so...
You need [class name] in front because there are many situations in which the first [class name] is different from the second, like:
IMyCoolInterface obj = new MyInterfaceImplementer();
MyBaseType obj2 = new MySubTypeOfBaseType();
etc. You can also use the word 'var' if you don't want to specify the type explicitely.
Why do we need to know the data type
before a class instance?
You don't! Read from right to left. You create the variable and then you store it in a type safe variable so you know what type that variable is for later use.
Consider the following snippet, it would be a nightmare to debug if you didn't receive the errors until runtime.
void FunctionCalledVeryUnfrequently()
{
ClassA a = new ClassA();
ClassB b = new ClassB();
ClassA a2 = new ClassB(); //COMPILER ERROR(thank god)
//100 lines of code
DoStuffWithA(a);
DoStuffWithA(b); //COMPILER ERROR(thank god)
DoStuffWithA(a2);
}
When you'r thinking you can replace the new Class() with a number or a string and the syntax will make much more sense. The following example might be a bit verbose but might help to understand why it's designed the way it is.
string s = "abc";
string s2 = new string(new char[]{'a', 'b', 'c'});
//Does exactly the same thing
DoStuffWithAString("abc");
DoStuffWithAString(new string(new char[]{'a', 'b', 'c'}));
//Does exactly the same thing
C#, as others have pointed out, is a strongly, statically-typed language.
By stating up front what the type you're intending to create is, you'll receive compile-time warnings when you try to assign an illegal value. By stating up front what type of parameters you accept in methods, you receive those same compile-time warnings when you accidentally pass nonsense into a method that isn't expecting it. It removes the overhead of some paranoia on your behalf.
Finally, and rather nicely, C# (and many other languages) doesn't have the same ridiculous, "convert anything to anything, even when it doesn't make sense" mentality that PHP does, which quite frankly can trip you up more times than it helps.
c# is a strongly-typed language, like c++ or java. Therefore it needs to know the type of the variable. you can fudge it a bit in c# 3.0 via the var keyword. That lets the compiler infer the type.
That's the difference between a strongly typed and weakly typed language. C# (and C, C++, Java, most more powerful languages) are strongly typed so you must declare the variable type.
When we define variables to hold data we have to specify the type of data that those variables will hold. The compiler then checks that what we are doing with the data makes sense to it, i.e. follows the rules. We can't for example store text in a number - the compiler will not allow it.
int a = "fred"; // Not allowed. Cannot implicitly convert 'string' to 'int'
The variable a is of type int, and assigning it the value "fred" which is a text string breaks the rules- the compiler is unable to do any kind of conversion of this string.
In C# 3.0, you can use the 'var' keyword - this uses static type inference to work out what the type of the variable is at compile time
var foo = new ClassName();
variable 'foo' will be of type 'ClassName' from then on.
One things that hasn't been mentioned is that C# is a CLS (Common Language Specification) compliant language. This is a set of rules that a .NET language has to adhere to in order to be interopable with other .NET languages.
So really C# is just keeping to these rules. To quote this MSDN article:
The CLS helps enhance and ensure
language interoperability by defining
a set of features that developers can
rely on to be available in a wide
variety of languages. The CLS also
establishes requirements for CLS
compliance; these help you determine
whether your managed code conforms to
the CLS and to what extent a given
tool supports the development of
managed code that uses CLS features.
If your component uses only CLS
features in the API that it exposes to
other code (including derived
classes), the component is guaranteed
to be accessible from any programming
language that supports the CLS.
Components that adhere to the CLS
rules and use only the features
included in the CLS are said to be
CLS-compliant components
Part of the CLS is the CTS the Common Type System.
If that's not enough acronyms for you then there's a tonne more in .NET such as CLI, ILasm/MSIL, CLR, BCL, FCL,
Because C# is a strongly typed language
Static typing also allows the compiler to make better optimizations, and skip certain steps. Take overloading for example, where you have multiple methods or operators with the same name differing only by their arguments. With a dynamic language, the runtime would need to grade each version in order to determine which is the best match. With a static language like this, the final code simply points directly to the appropriate overload.
Static typing also aids in code maintenance and refactoring. My favorite example being the Rename feature of many higher-end IDEs. Thanks to static typing, the IDE can find with certainty every occurrence of the identifier in your code, and leave unrelated identifiers with the same name intact.
I didn't notice if it were mentioned yet or not, but C# 4.0 introduces dynamic checking VIA the dynamic keyword. Though I'm sure you'd want to avoid it when it's not necessary.
Why C# requires me to specify the data type when creating a variable.
Why do we need to know the data type before a class instance?
I think one thing that most answers haven't referenced is the fact that C# was originally meant and designed as "managed", "safe" language among other things and a lot of those goals are arrived at via static / compile time verifiability. Knowing the variable datatype explicitly makes this problem MUCH easier to solve. Meaning that one can make several automated assessments (C# compiler, not JIT) about possible errors / undesirable behavior without ever allowing execution.
That verifiability as a side effect also gives you better readability, dev tools, stability etc. because if an automated algorithm can understand better what the code will do when it actually runs, so can you :)
Statically typed means that Compiler can perform some sort of checks at Compile time not at run time. Every variable is of particular or strong type in Static type. C# is strongly definitely strongly typed.
Isn't it much more elegant and neat to have an IStringable interface?
Who needs this Type.FullName object returned to us?
EDIT: everyone keeps asking why do I think it's more elegant..
Well, it's just like that, instead of IComparable, object would have CompareTo method, that by default throws an exception or returns 0.
There are objects that cannot and should not be described as a string. object could have equally returned string.Empty. Type.FullName is just an arbitrary choice..
And for methods such as Console.Write(object), I think it should be: Write(IStringable).
However, if you are using WriteLine to anything but strings (or something that its ToString is obvious such as numbers), it seems to me it's for debugging mode only..
By the way - how should I comment to you all? Is it okay that I post an answer?
There are three virtual methods that IMHO should have never been added to System.Object...
ToString()
GetHashCode()
Equals()
All of these could have been implemented as you suggest with an interface. Had they done so I think we'd be much better off. So why are these a problem? Let's just focus on ToString():
If ToString() is expected to be implemented by someone using ToString() and displaying the results you have an implicit contract that the compiler cannot enforce. You assume that ToString() is overloaded, but there is no way to force that to be the case.
With an IStringable you would only need to add that to your generic type-constraint or derive your interface from it to require it's usage on implementing objects.
If the benefit you find in overloading ToString() is for the debugger, you should start using [System.Diagnostics.DebuggerDisplayAttribute].
As for needing this implementation for converting objects to strings via String.Format(), and/or Console.WriteLine, they could have deferred to the System.Convert.ToString(object) and checked for something like 'IStringable', failing over to the type's name if not implemented.
As Christopher Estep points out, it's culture specific.
So I guess I stand alone here saying I hate System.Object and all of it's virtual methods. But I do love C# as a whole and overall I think the designers did a great job.
Note: If you intend to depend upon the behavior of ToString() being overloaded, I would suggest you go ahead and define your IStringable interface. Unfortunatly you'll have to pick another name for the method if you really want to require it.
more
My coworkers and I were just speaking on the topic. I think another big problem with ToString() is answering the question "what is it used for?". Is it Display text? Serialization text? Debugging text? Full type name?
Having Object.ToString makes APIs like Console.WriteLine possible.
From a design perspective the designers of the BCL felt that the ability to provide a string representation of an instance should be common to all objects. True full type name is not always helpful but they felt the ability to have customizable representation at a root level outweighed the minor annoyance of seeing a full type name in output.
True you could implement Console.WriteLine with no Object.ToString and instead do an interface check and default to the full name of the type if the interface was not present. But then every single API which wanted to capture the string representation of an object instance would have to implement this logic. Given the number of times Object.ToString is used just within the core BCL, this would have lead to a lot of duplication.
I imagine it exists because it's a wildly convenient thing to have on all objects and doesn't require add'l cruft to use. Why do you think IStringable would be more elegant?
Not at all.
It doesn't need to be implemented and it returns culture-specific results.
This method returns a human-readable string that is culture-sensitive. For example, for an instance of the Double class whose value is zero, the implementation of Double..::.ToString might return "0.00" or "0,00" depending on the current UI culture.
Further, while it comes with its own implementation, it can be overriden, and often is.
Why make it more complicated? The way it is right now basically establishes that each and every object is capable of printing its value to a string, I can't see anything wrong with that.
A "stringable" representation is useful in so many scenarios, the library designers probably thought ToString() was more straightforward.
With IStringable, you will have to do an extra check/cast to see if you can output an object in string format. It's too much of a hit on perf for such a common operation that should be a good thing to have for 99.99% of all objects anyway.
Mmmm, so it can be overridden in derived classes possibly?
Structs and Objects both have the ToString() member to ease debugging.
The easiest example of this can be seen with Console.WriteLine which receives a whole list of types including object, but also receives params object[] args. As Console is often a layer on-top of TextWriter these statements are also helpful (sometimes) when writing to files and other streams (sockets).
It also illustrates a simple object oriented design that shows you interfaces shouldn't be created just because you can.
My new base class:
class Object : global::System.Object
{
[Obsolete("Do not use ToString()", true)]
public sealed override string ToString()
{
return base.ToString();
}
[Obsolete("Do not use Equals(object)", true)]
public sealed override bool Equals(object obj)
{
return base.Equals(this, obj);
}
[Obsolete("Do not use GetHashCode()", true)]
public sealed override int GetHashCode()
{
return base.GetHashCode();
}
}
There's indeed little use of having the Type.FullName returned to you, but it would be even less use if an empty string or null were returned. You ask why it exists. That's not too easy to answer and has been a much debated issue for years. More then a decade ago, several new languages decided that it would be convenient to implicitly cast an object to a string when it was needed, those languages include Perl, PHP and JavaScript, but none of them is following the object orientation paradigm thoroughly.
Approaches
Designers of object oriented languages had a harder problem. In general, there were three approaches for getting the string representation of an object:
Use multiple inheritance, simply inherit from String as well and you can be cast to a string
Single inheritance: add ToString to the base class as a virtual method
Either: make the cast operator or copy constructor overloadable for strings
Perhaps you'd ask yourself Why would you need a ToString or equiv. in the first place? As some others already noted: the ToString is necessary for introspection (it is called when you hover your mouse over any instance of an object) and the debugger will show it too. As a programmer, you know that on any non-null object you can safely call ToString, always. No cast needed, no conversion needed.
It is considered good programming practice to always implement ToString in your own objects with a meaningful value from your persistable properties. Overloads can help if you need different types of representation of your class.
More history
If you dive a bit deeper in the history, we see SmallTalk taking a wider approach. The base object has many more methods, including printString, printOn etc.
A small decade later, when Bertrand Meyer wrote his landmark book Object Oriented Software construction, he suggested to use a rather wide base class, GENERAL. It includes methods like print, print_line and tagged_out, the latter showing all properties of the object, but no default ToString. But he suggests that the "second base object ANY to which all user defined object derive, can be expanded", which seems like the prototype approach we now know from JavaScript.
In C++, the only multiple inheritance language still in widespread use, no common ancestor exists for all classes. This could be the best candidate language to employ your own approach, i.e. use IStringable. But C++ has other ways: you can overload the cast operator and the copy constructor to implement stringability. In practice, having to be explicit about a to-string-implementation (as you suggest with IStringable) becomes quite cumbersome. C++ programmers know that.
In Java we find the first appearance of toString for a mainstream language. Unfortunately, Java has two main types: objects and value types. Value types do not have a toString method, instead you need to use Integer.toString or cast to the object counterpart. This has proven very cumbersome throughout the years, but Java programmers (incl. me) learnt to live with it.
Then came C# (I skipped a few languages, don't want to make it too long), which was first intended as a display language for the .NET platform, but proved very popular after initial skepticism. The C# designers (Anders Hejlsberg et al) looked mainly at C++ and Java and tried to take the best of both worlds. The value type remained, but boxing was introduced. This made it possible to have value types derive from Object implicitly. Adding ToString analogous to Java was just a small step and was done to ease the transition from the Java world, but has shown its invaluable merits by now.
Oddity
Though you don't directly ask about it, but why would the following have to fail?
object o = null;
Console.WriteLine(o.ToString());
and while you think about it, consider the following, which does not fail:
public static string MakeString(this object o)
{ return o == null ? "null" : o.ToString(); }
// elsewhere:
object o = null;
Console.WriteLine(o.MakeString());
which makes me ask the question: would, if the language designers had thought of extension methods early on, the ToString method be part of the extension methods to prevent unnecessary NullPointerExceptions? Some consider this bad design, other consider it a timesaver.
Eiffel, at the time, had a special class NIL which represented nothingness, but still had all the base class's methods. Sometimes I wished that C# or Java had abandoned null altogether, just like Bertrand Meyer did.
Conclusion
The wide approach of classical languages like Eiffel and Smalltalk has been replaced by a very narrow approach. Java still has a lot of methods on Object, C# only has a handful. This is of course good for implementations. Keeping ToString in the package simply keeps programming clean and understandable at the same time and because it is virtual, you can (and should!) always override it, which will make your code better apprehendable.
-- Abel --
EDIT: the asker edited the question and made a comparison to IComparable, same is probably true for ICloneable. Those are very good remarks and it is often considered that IComparable should've been included in Object. In line with Java, C# has Equals and not IComparable, but against Java, C# does not have ICloneable (Java has clone()).
You also state that it is handy for debugging only. Well, consider this everywhere you need to get the string version of something (contrived, no ext. methods, no String.Format, but you get the idea):
CarInfo car = new CarInfo();
BikeInfo bike = new BikeInfo();
string someInfoText = "Car " +
(car is IStringable) ? ((IStringable) car).ToString() : "none") +
", Bike " +
(bike is IStringable) ? ((IStringable) bike).ToString() : "none");
and compare that with this. Whichever you find easier you should choose:
CarInfo car = new CarInfo();
BikeInfo bike = new BikeInfo();
string someInfoText = "Car " + car.ToString() + ", Bike " + bike.ToString();
Remember that languages are about making things clearer and easier. Many parts of the language (LINQ, extension methods, ToString(), the ?? operator) are created as conveniences. None of these are necessities, but sure are we glad that we have them. Only when we know how to use them well, we also find the true value of a feature (or not).
I'd like to add a couple of thoughts on why .NET's System.Object class definition has a ToString() method or member function, in addition to the previous postings on debugging.
Since the .NET Common Language Runtime (CLR) or Execution Runtime supports Reflection, being able to instantiate an object given the string representation of the class type seems to be essential and fundamental. And if I'm not mistaken, all reference values in the CLR are derived from System.Object, having the ToString() method in the class ensures its availability and usage through Reflection. Defining and implementing an interface along the lines of IStringable, is not mandatory or required when defining a class in .NET, and would not ensure the ability to dynamically create a new instance after querying an assembly for its supported class types.
As more advanced .NET functionality available in the 2.0, 3.0 and 3.5 runtimes, such as Generics and LINQ, are based on Reflection and dynamic instantiation, not to mention .NET's Dynamic Language Runtime (DLR) support that allow for .NET implementations of scripting languages, such as Ruby and Python, being able to identify and create an instance by a string type seems to be an essential and indispensable function to have in all class definitions.
In short, if we can't identify and name a specific class we want to instantiate, how can we create it? Relying on a ToString() method that has the base class behavior of returning the Class Type as a "human readable" string seems to make sense.
Maybe a review of the articles and books from Jeffrey Ricther and Don Box on the .NET Framework design and architecture may provide better insights on this topic as well.
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.