Today I read an article where it's written that we should always use TryParse(string, out MMM) for conversion rather than Convert.ToMMM().
I agree with article but after that I got stuck in one scenario.
When there will always be some valid value for the string and hence we can also use Convert.ToMMM() because we don't get any exception from Convert.ToMMM().
What I would like to know here is: Is there any performance impact when we use TryParse because when I know that the out parameter is always going to be valid then we can use Convert.ToMMM() rather TryParse(string, out MMM).
What do you think?
If you know the value can be converted, just use Parse(). If you 'know' that it can be converted, and it can't, then an exception being thrown is a good thing.
EDIT: Note, this is in comparison to using TryParse or Convert without error checking. If you use either of the other methods with proper error checking then the point is moot. I'm just worried about your assumption that you know the value can be converted. If you want to skip the error checking, use Parse and die immediately on failure rather than possibly continuing and corrupting data.
When the input to TryParse/Convert.ToXXX comes from user input, I'd always use TryParse. In case of database values, I'd check why you get strings from the database (maybe bad design?). If string values can be entered in the database columns, I'd also use TryParse as you can never be sure that nobody modifies data manually.
EDIT
Reading Matthew's reply: If you are unsure and would wrap the conversion in a try-catch-block anyway, you might consider using TryParse as it is said to be way faster than doing a try-catch in that case.
There is significant difference regarding the developing approach you use.
Convert: Converting one "primitive" data in to another type and corresponding format using multiple options
Case and point - converting an integer number in to its bit by bit representation. Or hexadecimal number (as string) in to integer, etc...
Error Messages : Conversion Specific Error Message - for problems in multiple cases and at multiple stages of the conversion process.
TryParse: Error-less transfer from one data format to another. Enabling T/F control of possible or not.
Error Messages: NONE
NB: Even after passing the data in to a variable - the data passed is the default of the type we try to parse in to.
Parse: in essence taking some data in one format and transfer it in to another. No representations and nothing fancy.
Error Messages: Format-oriented
P.S. Correct me if I missed something or did not explain it well enough.
Related
I encountered a scenario where i have to send an array of integers as parameter from specflow feature file. I could have used tables which i don't want to do as i have send as row[] or col[]. If i pass parameter as a string
eg: Given set the value as '470,471,472,472'
and receive it and do split in step definition file. How different is StepArgumentTransformation from the above scenario? Is any other benefit in using step argument transformation. I understand we can convert XML,Date or any object. Why do we have to use stepargumenttransformation???
I hope I understood the question correctly.
Specflow supports some automatic transformation out of the box, so things like converting to Date, Double, int etc etc, and it does these by default as there is no ambiguity about them. You can easily convert a string to a double or a Date as you know the locale being used.
Why isn't converting to arrays supported? I suppose it could be, but there is some ambiguity. What should the list separator be? a comma? What about locales that use that as a separator between the whole and fractional part of a number?
So providing a default implementation of something which converted a list to int[] or IEnumerable<int> could be possible, but its just likely to get some people asking why it doesn't work for them when they have used ☃ as a list separator.
It's better to leave the things with ambiguity to individuals to implement, rather than guess at the best implementation.
The StepArgumentTransformation you want is very simple to write and could be included in an external step assembly if you wanted to share it amongst many projects.
So to answer your many questions:
It's not really any different, it just encapsulates it in a single place, which is good practise, which is a benefit.
Yes you can convert any object.
You don't have to use StepArgumentTransformation, many people don't, but IMHO they make your life much easier
I have a textbox with date format dd/MM/yyyy that I want to convert to the format yyyy-MM-dd to insert it into a database.
I tried
Convert.DateTime/DateTime.ParseExact
but it always give me the system's default date format.
I don't know any other method to convert it in C#...
You shouldn't be converting it to a string at all to insert it into your database. (I'm surprised at all the other answers which are recommending this approach.)
Instead, you should be using parameterized SQL, and set the value of the parameter to the DateTime value you've got. You should be using parameterized SQL anyway to avoid SQL injection attacks, and to keep your code and data separate. The fact that it avoids unnecessary string conversions (each of which is a potential pain point) is yet another benefit.
This part of your question suggests you've got a fundamental misconception:
I used Convert.DateTime/DateTime.ParseExact it always give me system date format.
Those methods will give you a DateTime. A DateTime doesn't have a format. When you call ToString you just get the default format for the current culture, but that's not part of the value. It's like with numbers - 16 and 0x10 are the same number, and the int doesn't "know" whether it's in decimal or hex; it's a meaningless concept.
All of this goes beyond your immediate problem, towards trying to keep your code base clean in terms of types. You should keep data in its most appropriate form for as much of the time as you possibly can, and make sure you understand exactly what that data means at all points. Conversions to other types (such as strings) for communication should be done only at API/system boundaries, and avoided even there if possible (e.g. using parameterized SQL as in this case).
There are many methods but none so useful and logical than using Parametrized SQL. Here's the Wikipedia page! For more information on Parametrized SQL statements, Visit this Coding Horror page!
There is actually no need to change it. This is just the display format, but the 'DateTime' object inside stays the same. Depending on how you want to insert, you can just use:
string dateValue = DateTime.Now.ToString("yyyy-MM-dd");
And insert this in your query string.
EDIT
But as Jon Skeet commented, building your query string manually like this should never be done. A cleaner approach like parameterized SQL or utilizing NHibernate should be your first concern.
Hope this works!
DateTime variable= Convert.ToDateTime(your date);
You can format it like this:
string sDateTime = Convert.ToDateTime(txtTextBox.Text).ToString("yyyy-MM-dd");
Edit
There are many ways to skin a cat when it comes to preparing information for entry into a database. My solution here answers the OP directly, however I very much acknowledge that there are better ways to do this.
I'd suggest reading through Jon Skeet's post on this page as well, as he raises some extremely valid points regarding the approach of the OP.
Hope that helps.
I have a C# function that persists data to SQL-server through a stored procedure with a little more than 100 parameters. (Yes, I know, that's probably not a good design, but legacy code and lets not get into that here.) ;-)
For some reason this code now comes up with this error:
System.Data.SqlClient.SqlException was unhandled
Message=Error converting data type int to tinyint.
Now, I've taken a first look down the parameter- and variable-pairs, and there is no obvious culprit. (The parameters are of many datatypes, not just tinyint)
So what is the fastest way to determine the rogue variable? And does anybody know of a good way to either handle this proactively, by making the c#-side verify the variable against the parameter at run-time - or somehow extending the error message to tell exactly which parameter is failing?
Implementing an ORM is not an option at this stage.
Edit: I've started writing a function CheckParameters that will initially loop through the parameters and simply list the parameters and the corresponding value. I'm thinking it could be extended with actual knowledge of the different datatypes, but for now I just want it to aid in finding the bad variable.
Structure is as follows:
try
{
cmdStat.ExecuteNonQuery();
}
catch(SqlException)
{
CheckParameters(cmdStat.Parameters);
//re-throw
}
private void CheckParameters(SqlParameterCollection parameterCollection)
{
foreach (SqlParameter parameter in parameterCollection)
{
Trace.Write("{0}, {1}, {2}, {3}", parameter.ParameterName, parameter.DbType, parameter.SqlDbType, parameter.Value);
}
}
What I would do is replace the proc with a stub.
Then I'd binary chop half the parameters to be long enough to cope with int. If the error went away I'd binary chop only half, and check again. If the error didn't go away then I'd do the other half.
I suspect it would take at max less than 10 attempts to find it.
Is there a way to avoid casting to a non-string type when reading data from a text file containing exclusively integer values separated by integer markers ('0000' for example) ?
(Real-Life example : genetic DNA sequences, each DNA marker being a digit sequence.)
EDIT :
Sample data : 581684531650000651651561156843000021484865321200001987984948978465156115684300002148486532120000198798400009489786515611568430000214848653212000019879849480006516515611684531650000651651561156843000021 etc...
Unless I use a binary writer and read bytes, rather than text (because that is how data written at first), I think this a funky idea, so "NO" would be the straight answer for this.
Just wanted to get a definitive confirmation to that here, just to be definitely sure.
I welcome any intermediate solution to write/read this kind of data efficiently without having to code a custom reader GUI to display it outside my app, intelligibly (in some generic reader/viewer).
The short answer is no, because a text file is a string of characters.
The long answer is sort of yes; if you put your data into a format like XML, a deserializer can implicitly cast the data back to the correct type (without you having to do it manually) based on your schema.
If you have control over the format, consider using a binary format for your file and use e.g. BinaryReader.ReadInt32.
rather then just casting, you really should use the .TryParse(...) method(s) of the types you are trying to read. This is a much more type-safe solution.
And to answer your question, other then using a binary file, there is not (to my knowledge) a way to do this without casting (or using the TryParse methods)
The only way to control all the read process is to read bytes. Else you read strings.
Edit : I Didn't talk about automatic serialization via XML because of the details on the file format you gave.
If the data is text and you need to access it as an integer, a conversion will be required. The only question is which code does the conversion.
Depending upon the file format, you could look for classes or libraries that already handle them. Otherwise, keep your code well organized so you don't have to pay attention to the conversion too much.
Some options:
// Could throw exceptions
var x = Convert.ToInt32(text);
var x = Int32.Parse(text);
// Won't throw an exception, just check the results
int x = 0;
if (Int32.TryParse(text, out x)) { ... }
Im playing around with TryParse()
But lets say the parsing fails, then returns false, and ... nothing..
Is there a way to get info back about what failed the parsing?
I saw something like that at codeproject, but i didnt really understand it.
Thanks :)
No, there's no way of getting that information from the normal .NET routines. You could check for a few things manually:
Try parsing the number as a decimal. If that works, but parsing as an integer doesn't, then it's either out of the range of the integer, or it's not an integer.
Look for non-decimal, non +/-, non-decimal-point characters
Check whether it's an empty string
You haven't said what you're trying to parse (integer, double etc) or what options you want (allow hex, thousands separators etc) which makes it harder to give a good list of things to check.
The TryParse() method is there when you want to be shielded from any exceptions.
If you want to see the exceptions then why not use the standard Parse() method in a try/catch block which will allow you to view any FormatExceptions etc thrown?
As expected, with exception handling, this could impact performance however if the Parse() is expected to succeed then this should be tolerable.
Why not just use the regular Parse method instead?