I'm trying to parse my variable to its string representation typeName.
string typeName = property.PropertyType.ToString();
var propertyItem = (typeName)property.GetValue(templateData, null);
The string typeName should be the 'Type' of the property I have in my Model so somehow i want to parse it to that type. (at this moment it is List(InvoiceModel), but this may vary)
I hope this is enough information, otherwise please notify me. Thanks in advance.
property.GetValue returns the required object. From your code sample it seems that you don't know the object's type at compile time.
It is not possible to cast that object using (typename), and there is no use, because still you won't know the real type at compile time.
What you probably want to do is to use dynamic:
dynamic propertyItem = property.GetValue(templateData, null);
I think what you are looking for is property.GetType().ToString();
though you can't just put the varable in brackets to convert you need to use reflection to create the type
That said this entire idea is a bad idea, from the look of your code i think your trying to create some form of MetaData, if so then i would use an Enum to define your allowed datatypes, and i would only allow the simplest ones int, double, string, datetime etc and possibly an array's of such
in that case you would then do,
if(Property.Type == AllowedTyoes.String)
{
string stringval = Property.Value as string;
//use the string for a string safe function
}
if(Property.Type == AllowedTyoes.Int)
{
string stringval = Property.Value as string;
int tmp;
if(int.TryParse(stringval,out tmp))
{
//use the int for a int safe function
}
}
Related
I have been searching for a solution for quite a while now and couldn't find anything close.
What I want to achieve:
I have two strings, 'a' and 'b'. String 'a' contains a datatype, for example "Boolean".
String b contains a value like "1" or "False", could be anything.
I want to be able to store the value of string 'b' in a variable which has the datatype of string 'a'.
If I would itterate trough a list of results with the same values as given in the example the results would be as following:
Foreach(var value in MyList)
{
if(!var ConvertTo a) //Result would be negative because for "1" for it is not a boolean value, however if 'a' is "Int32" the result would be true.
continue;
else
{//The value "False" is convertable to boolean, so the result would true
Create a variable with datatype boolean with the value 'false'.
}
}
More or less i'm in search of some strangly hacked version of TryParse().
I used boolean in my example, but this can be any datatype. At least I should be able to handle atleast the following datatypes:
Int, Int32, Int64
string
Boolean
float, decimal
DateTime
My question:
Is it possible in any way to (try to) convert a value to any datatype given in a string?
I hope my question and example is clear, if not please leave a comment.
You have to map the strings to a type. Since not all of them are System.<yourType> directly, I would consider creating a mapping:
Dictionary<string, Type> types = new Dictionary<string, Type>();
types.Add("int", typeof(System.Int32);
//etc.
Then, use Convert.ChangeType to get your object:
object myObj = Convert.ChangeType(b, types[a]);
Maybe you could extend this by trying to get the type if the key does not exist in your type mapping:
object myObj = Convert.ChangeType(b, Type.GetType("System." + a));
in general if you know the type name you can do this:
Type type = Type.GetType("System.Data.OleDb.OleDbParameter");
for example, so you must anyway know the full name of the type.
said so, if you have an object which was set from the caller to a certain value, you can do a GetType() on the object and get its actual type.
if "True" comes as string, you have no way to distinguish if should be a bool or a string.
If you want to use the TimeSpan datatype, you cannot use ChangeType().
An alternative is to use TypeConverter.ConvertFrom():
var asString = "0";
var textType = "System.Int32";
var dataType = Type.GetType(textType);
var converter = TypeDescriptor.GetConverter(dataType);
var newValue = converter.CanConvertFrom(asString) ?
converter.ConvertFrom(asString) :
asString;
As with the other answers, it assumes you know what type you're casting to.
I read values from an local Access mdb-file. One value is stored as string in the db and I have it in a table. When using the GetType() method it return "System.String" and I can print it on the console without a problem but when I want to use it as an attribute for another method (requires a string) I get an error ("Cannot convert from 'object' to 'string'" and the same for 'int'). The same problems occur with some int values.
Am I doing something wrong or what is the problem in that case?
Console.WriteLine(dt.Rows[0][ProjName]); //prints project_name
Console.WriteLine(dt.Rows[0][ProjName].GetType()); //print "System.String"
Project = new Project(dt.Rows[0][ProjName], dt.Rows[0][MinDay], dt.Rows[0][MinWeek], dt.Rows[0][DayWeek]); //Error
Project = new Project(Convert.ToString(dt.Rows[0][ProjName]), Convert.ToInt32(dt.Rows[0][MinDay]), Convert.ToInt32(dt.Rows[0][MinWeek]), Convert.ToInt32(dt.Rows[0][DayWeek])); //Works Fine
Constructor for the Project Class:
public Project(string projectName, int hoursPerDay, int hoursPerWeek, int daysPerWeek)
You have stated in your answer is works when converting, and it is necessary as they are not strings and integers. They are objects. You can create a methid to handle it if you want.
public Project CreateProject(object projectName, object hoursPerDay, object hoursPerWeek, object daysPerWeek)
{
return new Project(projectName.ToString(), Convert.ToInt32(hoursPerDay), Convert.ToInt32(hoursPerWeek), Convert.ToInt32(daysPerWeek);
}
You have to explicitly cast the objects:
To cast to string use:
Object.ToString();
To cast to integers use:
Int32.TryParse(String, out int);
Your constuctor becomes
Project = new Project(dt.Rows[0][ProjName].ToString(), Int32.Parse(dt.Rows[0][MinDay]), Int32.Parse(dt.Rows[0][MinWeek]), Int32.Parse(dt.Rows[0][DayWeek]));
Note: Using Int32.Parse instead of Int32.TryParse assumes that the argument provided is a valid int at all times and does not give you a way to check if the casting has succeeded.
dt.Rows[0][ProjName] returns type object, and your method expects string. Even though you know it to be a string, it is not obvious to the compiler and must be specified explicitly using a cast, as you show in your last example, although just casting should be more efficient than converting unnecessarily:
Project = new Project((string)dt.Rows[0][ProjName], ...
This is a weird requirement I have. I know even my question is quite confusing. Here is what I want to know.
I've two string variables. I need to do equality comparison of the datatype of the underlying value in the string variables. For ex.
string firstVariable = "123"; // It contains integer value. i.e. I can convert it to integer value
string secondVariable = "string" // It contains string value.
Now I need to compare whether datatype of the underlying values of these two strings are same. How can I do this?
Update: Thanks to all for the clarifications and answers. How about if I know the type of one variable?
For ex:
int firstVariable;
string secondVariable = "123".
Is this possible to check whether the type of the first variable equals to converted value of the secondVariable. When I declared firstVariable as int it doesn't mean it is always int type. What I mean here is, I know the type of one variable and other variable is string and I want compare equality of the datatypes of firstvariable and value datatype of the secondVariable.
Is Convert.ChangeType will anyway help in the above scenario?
I know this is silly question, but out of curiosity in the language feature exploring, I wanted to know this.
There's no such thing as the "underlying data type".
Who's to say that "123" isn't just a string containing the digits 1, 2 and 3? Once you've converted a value to a string, any information about the value you converted from - including its type - is lost.
Written from my head so there may (will) be errors:
class StringTypeEqualityComparer : IEqualityComparer<string, string>
{
public bool Equals(string x, string y)
{
int tempInt;
if (Int32.TryParse(x, out tempInt) && (Int32.TryParse(y, out tempInt))
return true;
bool tempBool;
if (Boolean.TryParse(x, out tempBool) && Boolean.TryParse(y, out tempBool))
return true;
float tempFloat;
if (Single.TryParse(x, out tempFloat) && Single.TryParse(y, out tempFloat))
return true;
// And whatever other types you want to compare...
return false;
// But what if two regular strings should also evaluate to equal?
}
}
Why do you need to compare them by the underlying data type?. Just compare them as string. Or if you have another variable as string, just convert it to a string by calling ToString() and make the comparison on the string level.
To do it you have to have a limited list of possible data types and be sure that type of your string content is not ambiguous. Then, for each type, you can try to convert string to it, so you will be able to find what type it actually was.
Is there any way to detect the type from a given string input?
Eg:
string input = "07/12/1999";
string DetectType( s ) { .... }
Type t = DetectType(input); // which would return me the matched datatype. i.e. "DateTime" in this case.
Would I have to write this from scratch?
Just wanted to check if anybody knows of a better way before I went about it.
Thanks!
I'm pretty sure you'll have to write this from scratch - partly because it's going to be very strictly tailored to your requirements. Even a simple question such as whether the date you've given is December 7th or July 12th can make a big difference here... and whether your date formats are strict, what number formats you need to support etc.
I don't think I've ever come across anything similar - and to be honest, this sort of guesswork usually makes me nervous. It can be hard to get parsing right even when you know the data type, let alone when you're guessing at the data type to start with :(
You got to know something about the expected type.
If you do you could use TypeConverter e.g.:
public object DetectType(string stringValue)
{
var expectedTypes = new List<Type> {typeof (DateTime), typeof (int)};
foreach (var type in expectedTypes)
{
TypeConverter converter = TypeDescriptor.GetConverter(type);
if (converter.CanConvertFrom(typeof(string)))
{
try
{
// You'll have to think about localization here
object newValue = converter.ConvertFromInvariantString(stringValue);
if (newValue != null)
{
return newValue;
}
}
catch
{
// Can't convert given string to this type
continue;
}
}
}
return null;
}
Most system types have their own type converter, and you could write your own using the TypeConverter attribute on your class, and implementing your own converter.
Which (if any) is more correct? Why?
string someVariable = (string) someOtherVariable;
string someVariable = someOtherVariable.ToString();
string someVariable = someOtherVariable as string;
I've used all three, but I don't have any preference or understanding why one is better than the other.
These are not all examples of casting.
This is a cast:
string someVariable = (string) someOtherVariable;
This is method call:
string someVariable = someOtherVariable.ToString();
And this is a safe cast:
string someVariable = someOtherVariable as string;
The first and third examples are actual casts. The first cast has the potential to throw an InvalidCastException whereas the third example will not throw that exception. That is why the as operator is known as a safe cast.
Here's my article on the subject.
http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx
As for which one is "most correct", the one that is most correct is the one that has the meaning you intend to convey to the reader of the program.
"ToString()" conveys "this is probably not a string; if it is not, then I wish to obtain from the object a string which represents it."
The "cast" operator conveys either "this is a string, and I am willing to have my program crash if I am wrong", or the opposite, "this is not a string and I want to call a user-defined conversion on this object to string".
The "as" operator conveys "this might be a string and if it isn't, I want the result to be null."
Which of those four things do you mean?
The three do different things -- none are "more correct", it depends on your situation. If you have a bunch of objects that may not be strings, you'd probably use .ToString() (with a null check, if you expect nulls).
If you only care about the non-null strings, but still expect to be receiving non-strings, use an "as" cast, and then ignore the values that come in as null (they were either originally null, or of a non-string type)
if you expect to receive only strings, it is best to use the (string) cast. This expresses the intent best in the code.
object foo = 5;
string str = (string)foo; // exception
string str = foo as string; // null
string str = foo.ToString(); // "5"
object foo = "bar";
string str = (string)foo; // "bar"
string str = foo as string; // "bar"
string str = foo.ToString(); // "bar"
object foo = null;
string str = (string)foo; // null
string str = foo as string; // null
string str = foo.ToString(); // exception
The as keyword is very useful if you think the conversion will fail during an upcast. For instance, if I want to perform the same operation on similar types in a Control list... let's say unchecking all Checkboxes:
foreach (Control ctrl in Controls)
{
Checkbox box = ctrl as Checkbox;
if (box != null)
box.Checked = false;
}
This way, if my list has something else, like a text box or a label, no exception is thrown (as simply sets the variable = null if it fails), and it's very efficient. There is no exception overhead.
The ideas of CAST and CONVERT should not be confused here. Casting involves viewing an object as if it was another type. Converting involves transforming an object to another type.
If your intention is to CAST to a string, you should use the first or third. (Option depends on what you want to happen in the error condition. See bangoker's answer.)
If your intention is to CONVERT to a string, you should use the second. (Or better, ChaosPandion's modified statement with the trinary operator.) That is because the ToString method's behaviour is defined as converting the object into a string representation.
This is 100% personal preference here, but for me I use the folowing:
string someVariable = (string) someOtherVariable;
When converting to a child or parent type (eg. NetworkStream->Stream)
string someVariable = someOtherVariable.ToString();
When converting to a new type (int -> string)
And I never use the latter (as string) method, mostly because coming from a C/C++ background I prefer the() and it's a bit more concise.
There is a big difference between casting with parenthesis and casting with "as".
Basically, parenthesis will thrown an exception while "as" will return null instead of raising an exception.
More detailed info here
string someVariable = (string) someOtherVariable;
this is your good old normal casting and it will throw an exception if you try to cast something into something it CANNOT be casted (thus some times you need to check if they are castable)
string someVariable = someOtherVariable.ToString();
is not really casting, its executing a method that may come from different places(interfaces) but that ALL objects in C# have, since they inherit from the Object object, which has it. It has a default operation which is giving the name of the type of the object, but you can overload it to print whatever you want your class to print on the ToString method.
string someVariable = someOtherVariable as string;
This is a new c# casting, it will check first if it is castable by using a variable is string first and then doing the casting if it is valid or return null if it is not, so it could be a silent error if you are expecting exceptions, since you should check against null.
Basically
myType as myOtherType
is the same as:
var something = null;
if(myType is myOtherType)
{
something = (myType) myotherType;
}
except that as will check and cast in one step, and not in 2.
First of all, you should avoid casting with AS operator. The article linked explains why.
Second, you can use AS operator ONLY if you expect the value not being of the type you cast too. So you will have to check that manually.
Also the obj.ToString() method call is not a casting, it converts object to a string representation (which in case of a string itself is the same string). This can be ovveridden by any class.
So as a general rule I follow this:
Always use (Type) casting.
Use as operator only if object can be of other type than you cast to.
If using as operator - ALWAYS check the result for NULL.
UseToString only in cases when you need to display information about the object.
If your question about the best practice for syntax in casting a variable, then I prefer to use next one:
var someVariable = someOtherVariable as string ?? string.Empty;
Off course you can use someVariableDefaultValue instead of string.Empty.
In case if you cast not to string but into the some complex type, then I recommend next syntax, sometimes called the Safe Navigation Operator:
var complexVariable = otherComplexVariable as ComplexType;
if (complexVariable?.IsCondition)
{
//your code if cast passed and IsCondition is true
}
else
{
//your code if cast not passed or IsCondition is false
}