I have a question regarding type conversion in C#.
Object data_obj = "test";
string data_str;
data_str = data_obj;
this produces an error claiming no implicit conversion exists. Now, this is, at least for me, a little bit unintuitive, since Console.WriteLine("type{0}",data_obj.GetType()) produces System.String, but then again, i am really new at C#.
Now, getting past this, i would like to cast to the type of the data stored in data_obj, without having to switch and selecting the type manually.
So, basically, what i am asking is: is there a way to define an implicit conversion from System.Object to System.String, System.Decimal, etc.
Context:
I am reading from an ODBC connection to an SQLServer database and trying to pump those rows into an Oracle Database. Now, the correspondence of SQLServer and Oracle rows have to be defined. Now, i read the data from the SQLServer table with no problem whatsoever, and i store it in a List<Dictionary<string,Object>> (i know, storing the rows seem wrong, but design requirements, what can you do).
The insertion part is where i am having problems with the insertion. I basically loop (with a foreach) through the elements of the list and insert them row by row. It is here where i need to determine the type of the data stored in the Object.
Edit: Including a bit more detail.
No, there's no way of doing it implicitly. Options:
Call ToString() explicitly (which will throw an exception if the reference is null)
Call Convert.ToString()
Use "" + data_obj (ick, don't do it)
Cast if you're sure that data_obj is really a string
Why are you so keen on an implicit conversion though?
What you should be doing in your code as noted above is casting, not converting. The object in question is a string; you simply have stored it in an object reference.
Casting would be done like so:
data_str = (string)data_obj;
The overload of Console.Writeline you are mentioning takes a format string, and then a params array of object... not strings. It calls ToString() on each of those objects. So your call to data_obj.GetType().ToString() could be slimmed down to data_obj.GetType() (calling ToString() on a string just returns the string again)
As for an implicit conversion from object to type x... think about what you are asking; a reference of object can be any CLR type. How do you handle those conversions?
You could use the Convert.ToString method:
object o = ...
string s = Convert.ToString(o);
There is no implicit conversion from object to string in C#. However you could call the object's virtual ToString method
string s = o.ToString();
If you store your value in a var instead of type object and let the compiler decide what the value is, then it can be made implicit.
var data_obj = "test";
string data_str;
data_str = data_obj;
Related
ddlSomeDropDownType.SelectedValue is a dropdown of .aspx page.
I have the following code:
int num = int.Parse(((object)this.ddlSomeDropDownType.SelectedValue).ToString());
Am I correct in thinking that the following happens:
Drop down value (string) gets down-casted to object
Object is a reference type so .ToString() doesn't do anything in this instance, gets omitted by the compiler
Object then gets parsed to int: ref type => value type
Or would the C# compiler pick up on that, and not cast when it doesn't have to?
drop down value (string) gets down-casted to object
Well, yes, but all that changes is how subsequent calls to the object are bound by the compiler. You're telling the compiler "treat this value as an object" It does not change the actual object in any way.
object is a reference type so .ToString() doesn't do anything in this instance, gets omitted by compiler
No - you call ToString which is a virtual method on object, so either object.ToString or a subsequent override will get called (in your case, string.ToString()`.
Plus, you've told the compiler to treat the value as an object. You expect the compiler to go back and say "well, I know you told me to treat it as an object, but I can tell from the code above that it's a string, so I'm going to ignore that and just keep it as a string". The compiler will not go to that effort. The JIT optimizer may do something similar if there is an iron-clad guarantee that it will work; otherwise it will do what you told it to do.
object than gets cast to int
No - it is parsed by the int class - very different than casting. It will read the characters of the string and attempt to return an equivalent integer value. The original object (the string) is untouched, and a new value (the int) is created. If you "change" the original value (which is impossible in this case because strings are immutable, but for sake of argument let's assume you can) then the parsed integer would not change. If you casted the object to int and then changed the string, they are both referencing the same value, so and changes would be reflected in both.
Since SelectedValue is a string, there's no need to cast to object and then call ToString(), so your code could be simplified to
int num = int.Parse(this.ddlDiscountType.SelectedValue);
No, not really.
First, you need to understand the difference between runtime type information and compile-time type information.
The compile-time type of ddlDiscountType.SelectedValue is string. When you cast it to object, it doesn't change the runtime type, just the compile-time type - in effect, you reduced the public interface of the reference.
ToString is a virtual method, so as long as you don't use new, what happens depends on the runtime type, and has no relation to the compile-time type, as long as the method is defined in the compile-time type. Since ToString is defined on Object, there's no problem.
The compiler cannot remove the call to ToString, because you've explicitly said "No, this reference is not really a string. It's just an object.", so you do have to make the virtual method call. The call will use the runtime type of the reference, so you're executing String.ToString(), which just returns this. But you did all your best to interfere with the compiler, and the compiler isn't going to second-guess you.
Finally, int.Parse will parse the string and output an integer. This involves going character by character through the string, of course. Reference and value types aren't important here - it's not a cast, it's a method call like any other. The method converts a string to a number, that's it. A cast would simply throw an InvalidCastException, because a string is not an integer (though if you make your own type, you can provide your own cast methods, which can do whatever you want them to do). The compiler can't tell you that you can't cast a string to an integer, because you just said the reference isn't really a string, but rather an object - and an object can be casted to a int, if it refers to a runtime type that is a boxed int.
There's no reason to do things in such a complicated manner. Just do:
var number = int.Parse(ddlDiscountType.SelectedValue);
Spend your effort in adding proper error handling instead of doing silly rituals :)
1: That's not correct. "Drop Down value (string) is Up-casted into object ".All classes in the .NET Framework are derived from object.(casting toward Base class is up-casting.)
2: a) Yes object is reference type.
b).ToString is object class method(can be override by derived classes). Actually what's going on here is that int.Parse takes string parameter. For that you first covert that into object and then .ToString method calls.
3:Yes 3rd point is correct
i want to know typecasting in c# .net, i have below lines of code.
int i=4
object o = i // This works properly without any typecasting becausing boxing takes place automatically
string s= i // This does not work, even when the string is also reference type?
string s=(string)i //This also does not work even if i try to typecast the int to string.
string s= Convert.ToString(i); // this works.
so i want to know why string s = i and string s = (string)i does not work and whats the difference in using (string)i, i.ToString(), and Convert.ToString(i).
When it comes to boxing and unboxing, types have explicit and implicit casting. So, in some circumstances, it is easy enough for the runtime to allow for implicit conversion between two supported types, say an Int32 to a Double. However, there is no implicit or explicit conversion between an integer and a string, because obviously, a string is not an integer (despite the fact that a string can contain characters for an integer).
string s = i; // attempt at implicit cast from Int32 to String, error
object o = i; // all types inherit from Object, so you may implicitly or explicitly cast from Int32 to Object.
s = (string)i; // attempt at explicit cast from Int32 to string, error
s = i.ToString(); // conversion
s = Convert.ToString(i); // conversion
That's where Convert comes to play. Convert contains support for attempting to convert known primitives (and types supporting IConvertable) to another. So, ToString or Convert.ToString would be the preferred methods (ToString and Convert.ToString are virtually synonymous, except that ToString gives you some formatting options).
Well, string and object - both of them are reference types. However, object is a root type for all .NET types.
When you use such syntax as (string)i, you are trying to use explicit conversion beetween types. But this conversion type requires string class to know about all possible argument types.
So we have .ToString() method, which can be overriden in any class, and its return value is used as a string represenation of any object.
string s = i and string s = (string)i does not work
because I is not a string, and type CASTING is a CAST of the type, not a conversion. It only works if i contains a string or a subclass of string (which is not possible for strings, but may be for other classes).
whats the difference in using (string)i, i.ToString(), and Convert.ToString(i).
(string) i: cast i to a string, must be assignable.
i.ToString(): calls the ToSstring method, which is defiend on System.object, thus available on ALL classes and structs - but returns no sensible content if not overwritten.
Convert.ToString(i): coonverts i to a string. THis includes calling a converter which likely just calls ToString on this rare case.
At the end, casting is not aconversion. for (string) i to work i HAS TO BE A STRING, while convert tries to MAKE it a string.
You can specify implicit and explicit conversions in .net, the reason that string s = i fails is that there is no built in cast operation for an integer to a string.
see this MSDN article on casting for further information
string s= i does not work because the types don't match, int won't go into a string.
string s=(string)i does not work because it cannot asume which type conversion is to be used (i.e which base)
something like s = ""+i would work on the other hand as it would asume base 10 conversion.
so i want to know why string s = i and string s = (string)i does not work
The short answer is that there is no implict (first example above) nor explicit (second example above) cast from int to string defined. Slightly longer answer; when authoring the struct Int32 in C# no casting behaviour was programmed to enable the developer to automagically cast from an int to a string
whats the difference in using (string)i, i.ToString(), and Convert.ToString(i)
Well, the first doesn;t work as you said, and as ive explained above. The second calls the ToString method on the struct Int32, which returns (as the name implies) a string representation of the object. It should be noted that this is a brand new string, not in any way related to the original value. The third example Convert.ToString will, under the hood, call whatever the most appropriate way to turn the parameter passed in to a string - most likely just calls the ToString method - so pretty much identical to example 2.
ToString() method is override by each referance which is vitual method in the object class. string calss override that method and provide string value out of this.
The default implementation of the ToString method returns the fully qualified name of the type of the Object, as the following example shows.
Object obj = new Object();
Console.WriteLine(obj.ToString());
// The example displays the following output:
// System.Object
this behavior is inherited by reference types that do not override the ToString method.
Typecasting in C# only works along the lines of class inheritance. Object is the root of all types in C# and therefore all values can be typecast to it.
string and int do not share the same branch of inheritance and so cannot be directly cast from one to the other.
Convert.ToString() is a method designed to convert an integer to a string - there's no typecasting going on, it's just executing a method designed to convert an integer to a string representation.
i.ToString() performs the equivalent functionality to Convert.ToString(), except that i.ToString() has overloads which allow greater flexibility on the representation of the number in string format.
One last note, exceptions to the typecasting rules can be included by the developer by using a public static explicit operator method which permits the developer to convert one value to another as they see fit.
First thing to note is that every class derives from object.
Casting int to object is using an Int32.
Casting string to object is using a String.
There is no implicit cast from an integer to a string because they are in different parts of the class hierarchy - one does not in any way relate to another. However because string is used so often for output object (and therefore all its children) have a ToString() method for convenience.
However Convert is written specifically to be able to convert from one type to another, for example Convert.ToBool(x) can parse "true" or "false" to boolean, and as you have shown it can convert an integer to a string - again this is really a convenience that probably just calls Int32.ToString() under the hood.
whats the difference in the two string methods below?
string str1 = dr["RAGStatusCID"].ToString();
string str2 = (string)dr["Description"];
This will depend on what dr is. The first invokes the ToString method that each object could override on the indexer of the dr["RAGStatusCID"]. The second casts the dr["Description"] variable to a string.
If we use our telepathic skills and suppose that dr is a SqlDataReader then the two expression do pretty much the same thing except that the cast might throw an exception at runtime if the Description column is not a string.
You haven't mentioned the type of dr or what it's indexer operation returns, but ostensibly, these are two very different operations.
The first invokes the get indexer of dr and calls the ToString() method on the returned reference, allowing the object that reference refers to to provide a string representation of it's data. The generial intent of this is to allow the object itself to return a meaningful representation of itself as a string.
The second call attempts to cast the reference returned by the indexer to System.String. The object returned must either be an instance of System.String or must be a type that the compiler can invoke a custom conversion operator on. Here, the intent is to ensure that the object returned can be treated as an instance of System.String. You can read more about conversions (including user-defined ones) on MSDN.
First one calls the method that returns the string. Someone has to implement ToString method. Second one is just unboxing.
string str1 = dr["RAGStatusCID"].ToString();
This calls the .ToString() method on the object returned from the dr["RAGStatusCID"] call. It is guaranteed to return a string or null.
string str2 = (string)dr["Description"];
This attempts to cast the object returned by dr["Description"] to a string. If the object returned is not a string, then an exception is thrown.
in short, .toString() is a method, just like any other, (String) is a cast, a language construct used to treat one data type as another, compatible type.
Now for some detail:
.toString() is a method, just like any other method you may encounter. Its often thought to be a 'special' method in some way, but it isnt really, all it does is return a string. because its a member of the base Object type, it can be relied upon to be available in every object. For this reason it is generally used to provide a textual representation of the object of which it is member. By default, in c# this is the name of the type of the object. It is often desirable to override this method to provide a more meaningful name, but all it needs to do is return a string, this can be any string you like.
As noted before, theres nothing special about it, and you could just as easily have methods called ToInt(), ToDouble(), and ToChar() to provide the same functionality for there respective types.
Casting is a language construct, this means its built into the language and is implemented specifically for that language. It is used to enable compatible but different types to be used in different locations without the need for an explicit conversion.
xxx.ToString() calls a method on that object to convert it into a string object. (string)xxx assumes that the type of the object is already a string and simply performs a cast on the existing object. So in the first case a conversion happens, in the second it's just identifying the type explicitly.
To put it more succinctly, if in your example RagStatusCID is an integer and you attempted to call (string)dr["RagStatusCID"] you would get an exception because the type is not a string, it's an int. Calling .ToString() performs a conversion and the output is a string.
(string) is a casting operation. .ToString() is a method that is inherited from the Object class. Everything has a .ToString(), but not everything has a (string). Additionally certain objects will cast to a string different than the one .ToString() outputs.
I don't know if it is correct for C# but it probably is, so:
(String)myinstance calls implicitly the .toString() implementation of myinstance's class
if you have a class like this:
class User
{
private integer userId;
private integer userName;
... some code here...
public toString()
{
return "Username: " + this.userName + " (" + this.userId + ")";
}
}
with the method toString you are defining what (String)instance casting will do
User myuser = new User("Alex", 22);
String myuserdump = (String)myuser;
print(myuserdump);
will print "Username: Alex (22)"
I'm currently working on an application where I need to load data from an SQL database and then assign the retrieved values into the properties of an object. I'm doing this by using reflection since the property names and column names are the same. However, many of the properties are using a custom struct type that is basically a currency wrapper for the decimal type. I have defined an implicit conversion in my struct:
public static implicit operator Currency(decimal d)
{
return new Currency(d);
}
This works fine when I use it in code. However, when I have this:
foreach (PropertyInfo p in props)
{
p.SetValue(this, table.Rows[0][p.Name], null);
}
It throws an ArgumentException stating that it cannot convert from System.Decimal to Currency. I'm confused since it works fine in any other circumstance.
Unfortunately, these user-defined conversion operators are not used by the runtime; they are only used by the compiler at compile time. So if you take a strongly-typed decimal and assign it to a strongly-typed Currency, the compiler will insert a call to your conversion operator and everybody's happy. However, when you call SetValue as you're doing here, the runtime expects you to give it a value of the appropriate type; the runtime has no idea that this conversion operator exists, and won't ever call it.
I think you need to first unbox the value in table.Rows[0][p.Name] as a decimal.
In other words:
foreach (PropertyInfo p in props)
{
if (p.PropertyType == typeof(Currency))
{
Currency c = (decimal)table.Rows[0][p.Name];
p.SetValue(this, c, null);
}
else
{
p.SetValue(this, table.Rows[0][p.Name], null);
}
}
This is an issue I've seen once or twice before, so I actually decided to write a blog post about it. Anybody looking for a little more explanation, feel free to give it a read.
I assume that table is of type DataTable in your code, so the first indexer returns a DataRow, and the second one returns an object. Then PropertyInfo.SetValue also takes an object as the second argument. At no place in this code a cast happens in the code, which is why the overloaded conversion operator is not applied.
Generally speaking, it is only applied when static types are known (forgetting about dynamic in C# 4.0 for the moment). It is not applied when boxing and unboxing things. In this case, the indexer on DataRow boxes the value, and PropertyInfo.SetValue tries to unbox it to a different type - and fails.
Whilst I am not answering your problem, I think in this kind of situation it would be more appropriate to use a ORM Framework like the Entity Framework or NHibernate which will map your tables into your domain objects and handle all the conversions for you. Using something like reflection to figure out what fields to fill in a domain object is a slow way to do it.
This isn't really an issue, however I am curious. When I save a string in lets say an DataRow, it is cast to Object. When I want to use it, I have to cast it ToString. As far as I know there are several ways of doing this, first is
string name = (string)DataRowObject["name"]; //valid since I know it's a string
and another one is:
string name = DataRowObject["name"].ToString();
I am interested in what is the difference between both? Is the first more efficient? (This is just a speculation, in my head ToString() method is implemented by some looping mechanism where just casting it "could" be faster, however this is just a "gut feeling" I have).
Is there even a faster / more elegant way of doing this?
Can anyone clear this up for me?
The two are intended for different
purposes. The ToString method of any
object is supposed to return a string
representation of that object. Casting
is quite different, and the 'as' key
word performs a conditional cast, as
has been said. The 'as' key word
basically says "get me a reference of
this type to that object if that
object is this type" while ToString
says "get me a string representation
of that object". The result may be the
same in some cases but the two should
never be considered interchangeable
because, as I said, they exist for
different purposes. If your intention
is to cast then you should always use
a cast, NOT ToString.
from http://www.codeguru.com/forum/showthread.php?t=443873
see also http://bytes.com/groups/net-c/225365-tostring-string-cast
If you know it is a String then by all means cast it to a String. Casting your object is going to be faster than calling a virtual method.
Edit: Here are the results of some benchmarking:
============ Casting vs. virtual method ============
cast 29.884 1.00
tos 33.734 1.13
I used Jon Skeet's BenchmarkHelper like this:
using System;
using BenchmarkHelper;
class Program
{
static void Main()
{
Object input = "Foo";
String output = "Foo";
var results
= TestSuite.Create("Casting vs. virtual method", input, output)
.Add(cast)
.Add(tos)
.RunTests()
.ScaleByBest(ScalingMode.VaryDuration);
results.Display(ResultColumns.NameAndDuration | ResultColumns.Score,
results.FindBest());
}
static String cast(Object o)
{
return (String)o;
}
static String tos(Object o)
{
return o.ToString();
}
}
So it appears that casting is in fact slightly faster than calling ToString().
Basically in your case it is better to leave type cast because .ToString() may hide bugs. For example, your data base schema changed and name is no longer of string type but with .ToString() your code still works. So in this case it is better to use type cast.
Here is implementation of String.ToString() - nothing special =)
public override string ToString()
{
return this;
}
Downcasting is a relatively slow operation since CLR has to perform various runtime type-checks. However, in this particular scenario casting to string is more appropriate than calling ToString() for the sake of consistency (you can't call ToInt32 on object, but cast it to int) and maintanability.
I want to make one more comment
If you are going to use casting: string name = (string)DataRowObject["name"]
you will get an Exception: Unable to cast object of type 'System.DBNull' to type'System.String' in case if the record in the database table has null value.
In this scenario you have to use: string name = DataRowObject["name"].ToString() or
You have to check for null value like
if(!string.IsNullOrEmpty(DataRowObject["name"].ToString()))
{
string name = (string)DataRowObject["name"];
}
else
{
//i.e Write error to the log file
string error = "The database table has a null value";
}
For data object, I suggest you to use "as" keyword like the following code.
string name = DataRowObject["name"] as string;
Please check it before you use value.
if(name != null)
{
// statement for empty string or it has value
}
else
{
// statement for no data in this object.
}
In this case:
string name = DataRowObject["name"].ToString();
since it is a string, I think that the ToString() method of a string object is simple as:
return this;
so IMHO there is no performance penalty.
PS
I'm a Java programmer, so this anwser is only a guess.
ToString() does not perform a cast by default. Its purpose is to return a string that represents the type (e.g. "System.Object").
If you want to avoid casting you could try to think of an implementation that is strongly typed (using generics, for example) and avoids DataRowObject altogether.
I know you mentioned that the Object is a string, but incase you're afraid that the returned object is null, you can also cast using "Convert.ToString(DataRowObject["name"]);" This has the added benefit of returning an empty string (string.empty) if the object is null, to avoid any null reference exceptions (unless of course you want an exception thrown in such cases).