String casts in .NET - c#

Why is there so may ways to convert to a string in .net? The ways I have seen are .ToString, Convert.ToString() and (string). What is the Difference.

Convert.ToString(obj)
Converts the specified value to its equivalent String representation. Will return String.Empty if specified value is null.
obj.ToString()
Returns a String that represents the current Object. 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. The default implementation returns the fully qualified name of the type of the Object.
This method can be overridden in a derived class to return values that are meaningful for that type. For example, the base data types, such as Int32, implement ToString so that it returns the string form of the value that the object represents. Derived classes that require more control over the formatting of strings than ToString provides must implement IFormattable, whose ToString method uses the current thread's CurrentCulture property.
(string)obj
It's a cast operation, not a function call. Use it if you're sure that the object is of type string OR it has an implicit or explicit operator that can convert it to a string. Will return null if the object is null AND of type String or of type which implements custom cast to string operator. See examples.
obj as string
Safe cast operation. Same as above, but instead of throwing an exception it will return null if cast operation fails.
Hint: Don't forget to use CultureInfo with obj.ToString() and Convert.ToString(obj)
Example:
12345.6D.ToString(CultureInfo.InvariantCulture); // returns 12345.6
12345.6D.ToString(CultureInfo.GetCultureInfo("de-DE")); // returns 12345,6
Convert.ToString(12345.6D, CultureInfo.InvariantCulture); // returns 12345.6
Convert.ToString(12345.6D, CultureInfo.GetCultureInfo("de-DE")); // 12345,6
Convert.ToString(test); // String.Empty, "test" is null and it's type
// doesn't implement explicit cast to string oper.
Convert.ToString(null); // null
(string) null; // null
(string) test; // wont't compile, "test" is not a string and
// doesn't implement custom cast to string operator
(string) test; // most likely NullReferenceException,
// "test" is not a string,
// implements custom cast operator but is null
(string) test; // some value, "test" is not a string,
// implements custom cast to string operator
null as string; // null
Here is an example of custom cast operator:
public class Test
{
public static implicit operator string(Test v)
{
return "test";
}
}

.ToString() can be called from any object. However, if the type you call it on doesn't have a good implementation the default is to return the type name rather than something meaningful about the instance of that type. This method is inherited from the base Object type, and you can overload it in your own types to do whatever you want.
(string) is a cast, not a function call. You should only use this if the object you need already is a string in some sense, or if you know there is a good implicit conversion available (like from int). This will throw an exception is the object cannot be converted (including when the object is null)
as string is another way to write (string), but it differs in that it returns null rather than throwing an exception if the cast fails.
Convert.ToString() attempts to actually convert the argument into a string. This is the best option if you don't really know much about the argument. It can be slow because it has to do a lot of extra work to determine what kind of results to return, but that same work also makes it the most robust option when you don't know very much about the argument. If nothing else is available, it will fall back to calling the argument's .ToString() method.
String.Format The string class' .Format method can also be used to convert certain types to strings, with the additional advantage that you have some control over what the resulting string will look like.
Serialization This is a little more complicated, but .Net includes a couple different mechanisms for converting objects into a representation that can be safely stored and re-loaded from disk or other streaming mechanism. That includes a binary formatter, but most often involves converting to a string in some format or other (often xml). Serialization is appropriate when you want to later convert the your string back into it's originating type, or if you want a complete representation of a complex type.

Convert.ToString() will return an empty string if the object is null .ToString and (String) will throw an exception. Convert.ToString will internally call .ToString() if the value is null it will return an empty String.

object.ToString() is the most basic way of retrieving a string representation of an object, and can be specifically implemented by the object.
Convert.ToString() expands on that and provides some specific overloads for primitive types (char, byte, int, double, etc.) that allow for some more type-specific functionality (like base conversion, for example)
(string) is a casting operator, and will only work if the type is either a string or has an implicit or explicit operator that can convert it to a string. Otherwise you'll get an InvalidCastException

Don't forget as string

ToString() is a method of object, and it will always work on a non-null reference, so you'll get something, but whether that something is what you want, is a different story.
Convert.ToString() will yield the same result in most cases, but isn't as flexible as Object.ToString() as you can't pass custom formatting rules.
(string) will cast your object to string, and if it isn't a string then you'll get an InvalidCastException().

Think.
ToString is a virtual method, and each type can implement it however it wants. Also System.Object provides default implementations so that it always succeeds.
Convert.ToString works only with nulls as well and allows you to use IFormat provier as noted in the comment.
Casting to string requires object to implement casting operator. Again, types can implement it however they like, but most types do not, so you may get an exception here.
Use .ToString as your best option.

.ToString() is an instance method which asks the object for its string representation. When the object is null, this will throw a exception.
(string) is a cast to the string type, which isn't a very good idea in most cases except for simple data types, since it can break (throw an exception) when it's null or an invalid cast
Convert.ToString() does a bit more checking than a simple cast, giving a more robust alternative to the cast. It will return the empty string when the object is null.

Not to nitpick but null is a valid value for a String object. Therefore (string) null does not throw any exceptions. Try it for yourselves:
using System;
namespace Test
{
class Program
{
public static void Main(string[] args)
{
string s = (string) null;
Console.WriteLine(s);
}
}
}

Related

How to use C# generics to simplify access to WinRT settings?

In WinRT, settings are stored as objects which means that you end up doing a lot of casting to get back to the type you want. Since that seems to map onto one of the reasons why generics were added to C#, I've been trying to simplify my code so that I can do something like:
public string LastRunVersion
{
get
{
return GetLocalSettingsValue<String>("LastRunVersion", null);
}
set
{
SetLocalSettingsValue("LastRunVersion", value);
}
}
The problem I'm having is with the signature for SetLocalSettingsValue. I tried:
private T GetLocalSettingsValue<T>(string tag, T defaultValue) where T:Object
but Object isn't allowed because it isn't a valid constraint. I know that I only store booleans and strings, so I then tried:
private T GetLocalSettingsValue<T>(string tag, T defaultValue) where T:String, bool
but the compiler says that "A type used as a constraint must be an interface, a non-sealed class or a type parameter".
What do I need to do with the definition in order to allow me to use string and bool?
Thanks.
Implementing two different methods, as Sriram suggests, does seem like the simplest solution for the immediate concern. That said, your generic approach is viable, has precedent, and will make it much easier to extend the code in the future.
In fact, what you tried was nearly correct. The main thing is that you don't actually need a constraint at all. The method declaration is fine without it, and though you don't show the method body, as long as all you need to do is cast some object reference to the type T, that will work:
private T GetLocalSettingsValue<T>(string tag, T defaultValue)
{
object value;
// initialize/retrieve the value somehow
// Check for value present, return default if missing, cast otherwise
return value != null ? (T)value : defaultValue;
}
In fact, since you are passing a default value, type inference will allow you to omit the type parameter in some cases. For example:
public string LastRunVersion
{
get { return GetLocalSettingsValue("LastRunVersion", (string)null); }
}
If you had a non-null default value, the above would be more interesting. :) With the null value, you have to cast it to string just for the compiler to know what the correct type is, which is practically the same as just providing the type parameter. But if you were passing a string literal or the value of a string variable, the type would be clear and the name of the type would not need to be provided at all (not even as a cast).
More interesting is the bool scenario:
public string LastRunVersion
{
get { return GetLocalSettingsValue("SomeBooleanSetting", false); }
}
Here, the literal has a clear type, and so you don't need to provide the type name in any form.
Finally, note that C# does have the idea of default values for types. If you want to support non-null, non-zero default values, then your current approach is good. However, if your defaults are always going to be things like null, false, or 0 (e.g. for an int, should you ever need to store something like that), then you don't need the default parameter at all:
private T GetLocalSettingsValue<T>(string tag)
{
object value;
// initialize/retrieve the value somehow
// Check for value present, return default if missing, cast otherwise
return value != null ? (T)value : default(T);
}
Any reference type will use null as the default. For value types, you will get whatever the value would be if you created an instance using the parameterless constructor (all value types have a parameterless constructor). Numeric types all default to their version of 0, bool defaults to false, etc.
Naturally, in that case you will always have to provide the type parameter, since there aren't any arguments from which the type parameter could be inferred.

A little bit of string cast

Update:
When a database returns a value through the scalar, it will always be an object. So when the value is returned you should have a preconceived notion of what the type will be. Why would you use ToString(); when you you have a SELECT which passes two parameters.
As if it doesn't exist it will always throw a null. So in my refactor I believed the as would be the proper approach. As ToString() will throw an error --- So what form of cast is it comparable to?
I've got some code I'm maintaining, but in apart of my refactor I came across a ToString() attached to an ExecuteScalar. My question would be, does the usage of ToString() equate to:
(string)command.ExecuteScalar();
Or would it represent this:
command.ExecuteScalar() as string;
Obviously the as string would fail gracefully, where the cast (string) would actually fall into an InvalidCastException. So when you call:
command.ExecuteScalar().ToString();
Which method of casting is it attempting to do?
No, it doesn't mean either of those - it simply means calling ToString() on whatever the value is.
In particular, if the value is not a string, it will convert it to a string anyway - whereas string would fail with InvalidCastException and the as would return null.
So for example:
object x = 10;
string a = x.ToString(); // "10"
string b = x as string; // null
string c = (string) x; // Bang
Of course, ToString() can still throw an exception too - most obviously if the target of the call is a null reference.
Personally, I would suggest using a cast if you know what the result type should be - although the result of ExecuteScalar is more commonly a numeric value (e.g. a count) rather than a string.
Yes, that means an exception will be thrown if you're wrong - but if your query isn't doing what it's meant to anyway, then stopping due to an exception may well be better than going ahead with a bogus view of the world. (See my blog post on casting vs as for more on this attitude.)
Neither, because Object.ToString() will returns you a string representation of the object. Regardless whether the query returns a varchar or int.
If command.ExecuteScalar() returns null then it would be something like null.ToString() which will break your production code.
also (string)command.ExecuteScalar() can break your code.
I would suggest to use below line
var result = command.ExecuteScalar() as string;
if(result != null)
{
//your code
}
Let's think about it for a bit.
When you do command.ExecuteScalar() you get back and object in a lot of cases based on the provider you get an int.
What happens is the order of operations triggers
Command.ExecuteScalar() gets and object back.
We are assuming he is an int for the excercise we get that int back.
To String gets called which is defined in the int32 object itself.
You get back the string that was determined inside.
For the most part toString is not meant to throw an exception if no one has implemented in the chain you just get the object type back which is the implementation on the object.
With that said in the case of the int it would probably be the one above. Note if execute scalar returns null to string will error out since null is not an object.
Hope that helps.
P.S. If you tell me the object type of ExecuteScalar i can give you a better answer.

C# null - is it an object

When I was writing C# code a few days ago I noticed that the compiler complained that I had to cast null to a specific object.
Does this mean that null is simply an uninstantiated version of the type? Or is it a singleton value of a Null class like Java (even though it has special privileges)?
EDIT: an example of the code giving the error would be:
public String duplicate(String toDuplicate)
{
return toDuplicate + toDuplicate;
}
public String duplicate(int? toDuplicate)
{
String asString = toDuplicate.toString();
return asString + asString;
}
public static int Main(string[] args)
{
//This needs to be cast:
duplicate(null);
//To:
duplicate((string)null);
}
The reason I commented on null in Java was after reading this:
There is also a special null type, the
type of the expression null, which has
no name. Because the null type has no
name, it is impossible to declare a
variable of the null type or to cast
to the null type. The null reference
is the only possible value of an
expression of null type. The null
reference can always be cast to any
reference type. In practice, the
programmer can ignore the null type
and just pretend that null is merely a
special literal that can be of any
reference type.
Found here: Is null an Object?
I get the error you refer when i have overloaded methods and the compiler can't resolve which method to call at compile time. Is that it?
According to the MSDN description:
The null keyword is a literal that represents a null reference, one that does not refer to any object. null is the default value of reference-type variables. Ordinary value types cannot be null. However, C# 2.0 introduced nullable value types.
null is the "uninstanciated reference" for any type. It is not a value. null has no defined type.
No - the null is just a literal for the null reference.
The reason you need to "cast" it in this way (I put the word cast in quotes because you are not really casting an instance of anything), is purely to help the compiler resolve which overload of a method you are calling, or the method you are calling even exists.
In your example, you need to specify that you are calling the method "duplicate" that takes a single string argument. If you omit the cast, then the compiler only knows that the method you intended to call is called "duplicate" and has a single argument, but can't tell what type the argument is - did you mean to call duplicate(string) or did you mean to call duplicate(some other type)? Should it compile, or should it error telling you the method you are trying to call does not exist?
You will also get the same issue if you had a duplicate(byte[]) defined, because now your call is ambiguous without the explicit cast.
No its not an object. null is the default value of reference-type variables. Ordinary value types cannot be null. but there is another set called nullable types.
You are probably referring to the fact that the following leads to a compiler error:
int? nullableInt = (somecondition) ? value : null;
Indeed you need to add a cast here:
int? nullableInt = (somecondition) ? value : (int?)null;
Even though I'm not able to explain this in detail, I'd suspect the following:
int? is actually a short form for Nullable<int>, so it is basically an object instance. When assigning an int value to nullableInt, a property of Nullable<int> will be set internally. Directly assigning null would also be ok.
The conditional assignment however, would return two different types: int in case somecondition is true and object (null) otherwise.
Now the compiler doesn't know how to handle this, as the ternary operator needs to return values of the same type. So you need to specify the desired "type for the null value".
Sorry if this is not a very deep technical explanation - I'm sure there's somebody who can elaborate this better, but it might help understand this better.

Parameter converted from null to DateTime.MinValue when called using Invoke in C# 2.0

I have code a bit like this
public class MyObject
{
private bool IsValidDay(ref DateTime theDate)
{
...
}
}
MethodInfo[] methods = myObjectInstance.GetType().GetMethod("IsValidDay", BindingFlags.Instance | BindingFlags.NonPublic);
object[] args = { null };
bool val = (bool)method.Invoke(myObjectInstance, args);
But when the method is called, from within the IsValidDay method, theDate is DateTime.MinValue. This seems awfully weird - I'd perhaps expect a NullReferenceException to be thrown but not an automatic conversion.
In case you are wondering, this is code in a unit test. (in use the method is typically called via a public method that takes object).
As far as some other code which is subsequently called is concerned, DateTime.MinValue and null are not the same thing, so it's a little bit of a problem.
Any clues?? Suggestions.
From MSDN:
Any object in this array that is not explicitly initialized with a value will contain the default value for that object type. For reference-type elements, this value is null. For value-type elements, this value is 0, 0.0, or false, depending on the specific element type.
The default value of DateTime is DateTime.MinValue:
DateTime.MinValue == new DateTime() // true
This explains why DateTime.MinValue gets passed to the method when you call it with null.
Note that you cannot pass null to the method anyway when you call it without reflection:
DateTime dt = null; // cannot assign null to value type
obj.IsValidDay(ref dt);
So I'd say you don't need to test your method with a null reference.
If you want your method to accept null, you can change the declaration to DateTime? as others have already pointed out:
private bool IsValidDay(ref DateTime? dt) { ... }
A DateTime variable can't be null. It's not a reference type, so there won't be a null reference exception.
You could do:
private bool IsValidDay(ref DateTime? theDate)
{
if(theDate.HasValue)...
}
Here's a link talking about nullable types:
http://msdn.microsoft.com/en-us/library/1t3y8s4s%28VS.80%29.aspx
I think I get what you are asking.... in the case of your code (especially because of the ref parameter, you can't have variance on a parameter with ref or out). It has to pass in a DateTime object. It can't be anything else.....so the null argument has to be converted to something to get the function to work.
DateTime has a value, I suggest you use DateTime? (or Nullable<DataTime>) to support nulls
Invoke() method takes an array of values for the target method parameters. According to MSDN, uninitialized elements of this array corresponding to the ref parameters will be initialized with the default value (in this case DateTime.MinValue) before the target method call.
Also, the value in the parameters array corresponding to the ref parameter will be updated after the target method call.
In your case you shouldn't test the method with a null value because it's not a valid value for the DateTime data type.
This is a comment from Invoke method doc in MSDN library:
"If the method or constructor represented by this instance takes a ref parameter, no special attribute is required for that parameter in order to invoke the method or constructor using this function. Any object in this array that is not explicitly initialized with a value will contain the default value for that object type. For reference-type elements, this value is null. For value-type elements, this value is 0, 0.0, or false, depending on the specific element type."
Also found this tutorial:
Passing "ref" Parameters
Only reference types can be null. DateTime (like int, bool, structs, and enums) is a Value Type. Therefore DateTime cannot be null, just like an enum can't be null. You can use the Nullable generic, by declaring it as DateTime?. This will allow you to check it for null.
In the end, in this case, I think I'll go with the notion that the method doesn't actually need to be tested vs null, and note to myself that invoking methods via reflection doesn't always throw an exception when a straight function call would.
Other people may find the nullable type suggestion useful (though I imagine everybody has conttoned onto these by now...)

C# - Conversion -Clarification

This could be a very basic question for prodigies.But I have a doubt to handle it.
During Conversion we are using :
int.Parse(someThing)
Convert.ToInt32 or Convert.ToString()....
(Int32)(someValue)
even we use "as"
What are the restrictions for using each?
int.Parse assumes a string as a parameter and as such is only suitable for converting raw string representations to integers
Convert.ToInt32() will attempt to convert pretty much any object to an integer representation. Where the representation isn't a valid int (i.e. using a float with the value 55.3 or a string containing a word) this will raise a FormatException. If the integer is too large to fit in an int then an OverflowException will occur.
(int) is a direct cast. It's basically saying "I know that this object is really an integer, treat it as such". If the object actually isnt an integer you'll get an invalid cast exception.
Finally, as behaves the same as a direct cast except where the object is not of the correct type it will assign null. Not sure how this applies to int with it being a non-nullable type but certainly usable with
int? myInt = someVar as int?;
Convert.ToNnnn has the restrictions stipulated by its overloads; for instance, you cannot call Convert.ToMyCustomType (since that method does not exist). You can pass pretty much anything into Convert.ToString (or Convert.ToInt32 or any other of the Convert.ToNnnn methods) but the result may not always make sense. Also, if the method fails to perform the conversion it may throw an InvalidCastException.
The regular type case ((int)someValue) can be used in all cases where there is an explicit conversion available. If you try to perform an illegal cast you will get an exception thrown at you.
The as keyword can be used to cast type to another (reference) type (and it will return null if it's not possible). The as keyword cannot be used with value types (such as Int32, Point or DateTime).
In my own code I typically use a mixture of them, but in general I follow the following scheme:
If I want to convert a string to a numeric type, I usually use the TryParse provided by that numeric type.
If I want to cast a class instance to a base class or interface, I usually use the as keyword.
In other cases I use regular type casting within try/catch blocks.
Convert.ToInt32 can convert from various types (DateTime, Decimal, etc) back to an integer, while int.Parse() only converts from a string.
If you're only parsing strings back to integers, Convert.ToInt32 is just an alias for int.Parse, so you might as well use int.Parse instead.
Regarding casting, you cannot cast a string to an integer, you have to convert it like mentioned above.
Consider that you are working with a database, and you have a column that is inefficiently declared as varchar while it stores integer data. You cannot do (int)dr["column"] when using a SqlDataReader for instance, you would have to use int.Parse(dr["column"].ToString()) instead. If the column was of the int column type in the database, you could then have used the cast: (int)dr["column"].

Categories

Resources