Both of these are accepted by the compiler:
ssMinnow = listStrLineElements[VESSEL_TO_AVOID].ToString();
ssMinnow = listStrLineElements[VESSEL_TO_AVOID];
Is one way preferable to the other? ToString() or not ToString(), that is the question.
It is not only redundant, but also is dangerous: if listStrLineElements[VESSEL_TO_AVOID] happens to be null, your application is going to throw an exception if you use ToString(); without ToString(), it would simply assign null to ssMinnow.
If listStrLineElements[VESSEL_TO_AVOID] returns a string, then yes, it is redundant. if it returns some other type, then no, it is not redundant.
in General your don't need to invoke the ToString() method is the object type returned is already a String.
in your example we cannot tell that as ssMinnow does not show the declaration type :I assume you have used var keyword which will work with both of them or listStrLineElements[VESSEL_TO_AVOID] returns already a String
Simply redundant. I prefer to leave off ToString() where its not needed but its a judgement call.
Don't use ToString if you are already returning a string. You're just adding unnecessary overhead.
It is not so simple as stated. Redundant, possibly; good or bad, a matter of opinion. Since toString() will be called anyway if the object is treated as a string somewhere, the explicit use of toString() can serve as a signpost to the developer reading the code. The explicit call describes more of the original intent than leaving it as an assumption for the compiler to fulfill.
Related
I noticed that in C# that the + operator takes a string on the left and an object on the right:
string output = "" + numbers.ElementAt(0);
//vs
string output = numbers.ElementAt(0).ToString();
Why is the default behavior to accept an object on the right and not a string? When I look other + operators for say int, it is strongly typed for int/int instead of int/object.
I know in C# all objects have the ToString() method, is this just a way to remove the need to call .ToString() in the first example above?
Why is the default behavior to accept an object on the right and not a string?
Well, first off, there is an overload that accepts two strings, and if you pass two strings that's the overload that will be used, so it is the default behavior. But if you pass a string and a non-string, then the (string, object) overload will be used.
As for why that overload is there, it's because the C# language designers felt that it was entirely sensible to concat a string to any object, and had a reasonable implementation for doing so for any type of object.
When I look other + operators for say int, it is strongly typed for int/int instead of int/object.
How would you implement a operator +(int, object) overload? I don't see any good implementation here, unlike with string concatenation.
I know in C# all objects have the ToString() method, is this just a way to remove the need to call .ToString() in the first example above?
It actually works if the object is null, whereas your solution does not. If you would account for that then yes, that is essentially all that the overload is doing.
is this just a way to remove the need to call .ToString() in the first example above
Yes.
String concatenation automatically transforms non-strings into strings.
Source: C# Language Specification: Addition operator, MSDN.
I work on developing an external API. I added a method to my public interface :
public void AddMode(TypeA mode);
public void AddMode(TypeB mode); // the new method, TypeB and TypeA are not related at all
It looked good, until one test broke that was passing a null . That made the compiler confused with ambiguous call. I fixed the test with casting the null.
However my question is :
Should I change the name just because of this?
Or should let the client do the cast as I did? (if they pass null for whatever reason)
What is the best in this case while designing APIs ?
Edit :
the call was like this AddMode(null) , not like :
TypeA vl = null;
AddMode(v1); // this doesn't cause a problem
An API should be designed so that it's easy to use correctly and hard to use incorrectly.
Your API is easy to use correctly:
AddMode(new TypeA());
does compile.
It's harder to use incorrectly:
AddMode(null);
does not compile. The user ist forced to do something like
AddMode((TypeA)null);
Which should make him think, whether this is expected usage. So I think your API is OK as it is.
I think that depends on how exceptional null as a value for the respective argument is.
Compare, for example, this ArgumentNullException constructor: It is most frequently called when an internal exception has to be set. Otherwise, this constructor, which excepts the name of the illegal argument, is passed. On odd occasions, the former has to be invoked because a custom message has to be supplied, but no internal exception is supplied (I usually do this when I'm throwing the exception for an array/collection argument that contains null, but is not null itself). So, in this case, I need the explicit cast, and I'd say it is acceptable there.
If your methods really do the same, but null is still a usual value, you might want to add a parameterless overload for the null variant (i.e. the explicit cast is still possible, but users can also call the parameterless overload instead).
If your methods do something somewhat different, and yet something else for null, you can think about disallowing null altogether for the methods you've shown and adding a parameterless overload for the null case.
Update: If null is not acceptable anyway (and will result in an exception), then you should leave the method as it is. Other than for testing purposes, there should never be any whatsoever situation in which a literal null would be passed to the method, as this will invariably yield an exception. Therefore, do not change your overload names in this case.
Is null valid input to this method anyway?
Personally I'd leave it as is as long as both overloads of AddMode related, since you'd expect AddMode(X) and AddMode(Y) to be doing something related to each other.
If they are not related in any way, then maybe a method name change is in order
Well, it depends either null value is acceptable value in your API.
If not just do not accept it, by not supporting it. So even if the consumer will try to use it with null the compiler will break on ambiguity problem.
If your API accepts a null as a possible parameter value, then you have to specify it in the documentation and mention it is necessary to cast it, and write some code samples to show how.
However, if you don not want the user to use null values, you might change TypeA and TypeB as a struct instead of a class, if your class design allow it.
I'm working on a simple API that will accept a number of IBehaviours which are then applied in configuration. I am designing this using the params keyword since often there is just one behaviour wanted, but sometimes more.
However, it is very important that behaviours are applied in the correct order.
public void Configure(string wow, params IBehaviour[] behaviours) { ... }
Configure("oh yes", new MustHappenFirst(), new MustHappenSecondly());
Does this
Technically imply that behaviours
occurs in the same order when
enumerating? (as in standard-wise,
not simply practically-wise).
Semantically and intuitively convey that same behaviour?
Thanks.
The evaluation of the arguments will happen in left-to-right order and they'll be put into the array in that order.
Note that if "null" is a valid value for a behaviour, you can get into trouble:
Configure("hello", null);
calls
Configure("hello", (IBehaviour[]) null);
not
Configure("hello", new IBehaviour[1] { null } );
so be careful with that.
Yes. When you use params, the compiler just turns the arguments into an array, in the same order that the arguments were listed in the program. They will always be in this order inside the method.
A call to:
Configure("wow", one, two, three);
Will always map to:
Configure("wow", new[] {one, two, three});
Yes. Parameters specified for a method using the params keyword will be placed in the params array in the order they are specified in the method call. This is generally understood to be so by developers, who are familiar with params-using methods like String.Format where the order of a formatting value in the parameter list is very important.
Yes; order is preserved.
Yes; this is fine.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Casting: (NewType) vs. Object as NewType
In C#, why ever cast reference types when you can use "as"?
Casting can generate exceptions whereas "as" will evaulate to null if the casting fails.
Wouldn't "as" be easier to use with reference types in all cases?
eg:
MyObject as DataGridView
rather than,
(DataGridView)MyObject
Consider the following alternatives:
Foo(someObj as SomeClass);
and:
Foo((SomeClass)someObj);
Due to someObj being of the wrong type, the first version passes null to Foo. Some time later, this results in a NullReferenceException being thrown. How much later? Depends on what Foo does. It might store the null in a field, and then minutes later it's accessed by some code that expects it to be non-null.
But with the second version, you find the problem immediately.
Why make it harder to fix bugs?
Update
The OP asked in a comment: isn't is easier to use as and then check for null in an if statement?
If the null is unexpected and is evidence of a bug in the caller, you could say:
SomeClass c = someObj as SomeClass;
if (c == null)
{
// hmm...
}
What do you do in that if-block? There are two general solutions. One is to throw an exception, so it is the caller's responsibility to deal with their mistake. In which case it is definitely simpler to write:
SomeClass c = (SomeClass)someObj;
It simply saves you writing the if/throw logic by hand.
There is another alternative though. If you have a "stock" implementation of SomeClass that you are happy to use where nothing better is available (maybe it has methods that do nothing, or return "empty" values, etc.) then you could do this:
SomeClass c = (someObj as SomeClass) ?? _stockImpl;
This will ensure that c is never null. But is that really better? What if the caller has a bug; don't you want to help find bugs? By swapping in a default object, you disguise the bug. That sounds like an attractive idea until you waste a week of your life trying to track down a bug.
(In a way this mimics the behaviour of Objective-C, in which any attempt to use a null reference will never throw; it just silently does nothing.)
operator 'as' work with reference types only.
Sometimes, you want the exception to be thrown. Sometimes, you want to try to convert and nulls are OK. As already stated, as will not work with value types.
One definite reason is that the object is, or could be (when writing a generic method, you may not know at coding-time) being cast to a value type, in which case as isn't allowed.
One more dubious reason is that you already know that the object is of the type in question. Just how dubious depends on how you already know that. In the following case:
if(obj is MyType)
DoMyTypeStuff((MyType)obj);
else
DoMoreGeneralStuff(obj);
It's hard to justify using as here, as the only thing it really does is add a redundant check (maybe it'll be optimised away, maybe it won't). At the other extreme, if you are half-way to a trance state with the amount of information you've got in you're brain's paged-in memory and on the basis of that you are pretty sure that the object must be of the type in question, maybe it's better to add in the check.
Another good reason is that the difference between being of the wrong type and being null gets hidden by as. If it's reasonable to be passing in a string to a given method, including a null string, but it's not reasonable to pass in an int, then val as string has just made the incorrect usage look like a completely different correct usage, and you've just made the bug harder to find and potentially more damaging.
Finally, maybe if you don't know the type of the object, the calling code should. If the calling code has called yours incorrectly, they should receive an exception. To either allow the InvalidCastException to pass back, or to catch it and throw an InvalidArgument exception or similar is a reasonable and clear means of doing so.
If, when you write the code to make the cast, you are sure that the cast should work, you should use (DataGridView)MyObject. This way, if the cast fails in the future, your assumption about the type of MyObject will cause an invalid cast exception at the point where you make the cast, instead of a null reference exception at some point later.
If you do want to handle the case where MyObject is not a DataGridView, then use as, and presumably check for it being null before doing anything with it.
tl;dr If your code assumes something, and that assumption is wrong at run-time, the code should throw an exception.
From MSDN (as (C# reference)):
the as operator only performs reference conversions and boxing conversions. The as operator cannot perform other conversions, such as user-defined conversions, which should instead be performed using cast expressions.
Taking into consideration all of the comments, we came across this just the other day and wondered why you would do a direct cast over using the keyword as. What if you want the cast to fail? This is sometimes the desirable effect you want from a cast if you're casting from a null object. You then push the exception up the call stack.
So, if you want something to fail, use a direct cast, if you're okay with it not failing, use the as keyword.
As is faster and doesn't throw exceptions. Therefore it is generally preferred. Reasons to use casts include:
Using as, you can only assign types that are lower in the inheritance tree to ones that are higher. For example:
object o = "abc" as object;
DataGridView d = "abc" as DataGridView // doesn't do anything
DataGridView could create a custom cast that does allow this. Casts are defined on the target type and therefore allow everything, as long as it's defined.
Another problem with as is that it doesn't always work. Consider this method:
IEnumerable<T> GetList<T>(T item)
{
(from ... select) as IEnumerable<T>
}
This code fails because T could also be a Value Type. You can't use as on those because they can never be null. This means you'll have to put a constraint on T, while it is actually unnecesary. If you don't know whether you're going to have a reference type or not, you can never use as.
Of course, you should always check for null when you use the as keyword. Don't assume no exceptions will be thrown just becase the keyword doesn't throw any. Don't put a Try {} Catch(NullReferenceException){} around it, that't unneccesary and bloat. Just assign the value to a variable and check for null before you use it. Never use it inline in a method call.
I'm familiar with using out to pass in a simple data type for manipulation, but I can't seem to figure out how to pass in this Queue<> without causing a compile error. Any ideas?
Code:
Queue<SqlCommand> insertScriptQueue = new Queue<SqlCommand>();
private void UpdateDefaultIndicator(int newDefaultViewID,
out (Queue<SqlCommand>) insertScriptQueue)
UpdateDefaultIndicator(newViewID, out (Queue<SqlCommand>)insertScriptQueue);
You're passing in a reference type. No need to use out.
You shouldn't be initializing an out variable. If you need to modify an in-scope variable, use ref instead.
As Ed points out in his comment, "modify" may not give you the full idea of what's happening here - an out parameter of a reference type will by definition be an initialized object at the end of the function call. As most other answers have pointed out, if you want to pass in an initialized object, ref is the stronger choice.
Queue<SqlCommand> insertScriptQueue;
private void UpdateDefaultIndicator(int newDefaultViewID,
out Queue<SqlCommand> insertScriptQueue){/*body*/}
UpdateDefaultIndicator(newViewID,out insertScriptQueue);
That works fine for me... What error are you getting?
Why do you want a "out" ...here...why dont you return the type instead ? Let method return Queue<> insteasd of void..will that work for you?
The Queue is going to be passed by reference anyway, its not a value type. Just don't use 'out'. UPDATE: Pardon me, I was thinking of 'ref' - but the fact that you're passing a Queue data type in, and not just an unallocated reference, makes me think that you want to be using 'ref' anyway. Except of course that you don't need to use 'ref' because the Queue isn't a value type; its already going to be passed in 'by reference', by default.
make sure that you are assigning insertScriptQueue some kind of value inside of the UpdateDefaultIndicator method
The answer to the original question, by the way, is that you're casting to Queue, and the cast is returning an interim reference. That reference is not assignable, and so is not a legal out parameter. Erich's code implements the fix for this problem.