Passing a value into an Exception String Message - c#

Why can't I add a variable value into a string using this code:
throw new ArgumentOutOfRangeException("Any Opening Type besides 'None', should have a minimum width value of 50. Your inputed value = {0}",value);
The error I get is: "CS1503: Argument 2: Cannot convert from 'int' to 'System.Exception?'"
But when I use this code it works fine:
throw new ArgumentOutOfRangeException($"Any Opening Type besides 'None', should have a minimum width value of 50. Your inputed value = {value}");
Can somebody help me understand why? As far as I know these two ways of doing it should result with the same end. I don't understand why it would be converting, shouldn't I then get the same error if I use a console.WriteLine method? What makes this special?

The first syntax only works for methods that use format strings. Some methods, like Console.WriteLine, have an overload that takes a format string as the first argument and any number of objects as a subsequent arguments array, so you're probably used to it working the same as when you use string interpolation syntax ($"...").
Most exception constructors don't follow that pattern, so you'll have to build your own string to pass in as their message argument. String interpolation syntax will do that for you automatically, as you've discovered. Or you can call string.Format explicitly:
throw new ArgumentOutOfRangeException(
string.Format(
"Any Opening Type besides 'None', should have a minimum width value of 50. Your inputed value = {0}",
value));

You should look at the documentation for the constructors of ArgumentOutOfRangeException. The parameters you provide do not match any of constructor parameter types so it throws an exception.
Instead you should format the string using String.Format() like:
throw new ArgumentOutOfRangeException(String.Format("Any Opening Type besides 'None', should have a minimum width value of 50. Your inputed value = {0}",value));

Related

How to initialize default value to C#7 out variables?

I used TryParse to parse a string to number. I need a solution to initialize out variable with default value, So when TryParse fails to convert I get my default value.
Here is the code :
long.TryParse(input.Code, out long Code = 123);
//Error CS1525 Invalid expression term '='
I want to strictly to use C#7 out variables standard.
Whilst the out parameter itself cannot take a default value, you can achieve what you want to do with a single expression in C# 7. You simply combine the out parameter with a ternary expression:
var code = long.TryParse(input.Code, out long result) ? result : 123;
You can't do it... The .NET runtime doesn't know anything of "success" or "failure" of long.TryParse. It only knows that TryParse has a bool return value and that after TryParse finishes, the out variable will be initialized. There is no necessary correlation between true and "there is a good value in result" and false and "there is no good value in result".
To make it clear, you could have:
static bool NotTryParse(string s, out long result)
{
return !long.TryParse(s, out result);
}
And now? When should your default value be used?

Strange behaviour of String.Format when (mis-)using placeholders

When I learned about the String.Format function, I did the mistake to think that it's acceptable to name the placeholders after the colon, so I wrote code like this:
String.Format("A message: '{0:message}'", "My message");
//output: "A message: 'My message'"
I just realized that the string behind the colon is used to define the format of the placeholder and may not be used to add a comment as I did.
But apparently, the string behind the colon is used for the placeholder if:
I want to fill the placeholder with an integer and
I use an unrecognized formating-string behind the colon
But this doesn't explain to me, why the string behind the colon is used for the placeholder if I provide an integer.
Some examples:
//Works for strings
String.Format("My number is {0:number}!", "10")
//output: "My number is 10!"
//Works without formating-string
String.Format("My number is {0}!", 10)
//output: "My number is 10!"
//Works with recognized formating string
String.Format("My number is {0:d}!", 10)
//output: "My number is 10!"
//Does not work with unrecognized formating string
String.Format("My number is {0:number}!", 10)
//output: "My number is number!"
Why is there a difference between the handling of strings and integers? And why is the fallback to output the formating string instead of the given value?
Just review the MSDN page about composite formatting for clarity.
A basic synopsis, the format item syntax is:
{ index[,alignment][:formatString]}
So what appears after the : colon is the formatString. Look at the "Format String Component" section of the MSDN page for what kind of format strings are predefined. You will not see System.String mentioned in that list. Which is no great surprise, a string is already "formatted" and will only ever appear in the output as-is.
Composite formatting is pretty lenient to mistakes, it won't throw an exception when you specify an illegal format string. That the one you used isn't legal is already pretty evident from the output you get. And most of all, the scheme is extensible. You can actually make a :message format string legal, a class can implement the ICustomFormatter interface to implement its own custom formatting. Which of course isn't going to happen on System.String, you cannot modify that class.
So this works as expected. If you don't get the output you expected then this is pretty easy to debug, you've just go two mistakes to consider. The debugger eliminates one (wrong argument), your eyes eliminates the other.
String.Format article on MSDN has following description:
A format item has this syntax: { index[,alignment][ :formatString] }
...
formatString Optional.
A string that specifies the format of the
corresponding argument's result string. If you omit formatString, the
corresponding argument's parameterless ToString method is called to
produce its string representation. If you specify formatString, the
argument referenced by the format item must implement the IFormattable
interface.
If we directly format the value using the IFormattable we will have the same result:
String garbageFormatted = (10 as IFormattable).ToString("garbage in place of int",
CultureInfo.CurrentCulture.NumberFormat);
Console.WriteLine(garbageFormatted); // Writes the "garbage in place of int"
So it seems that it is something close to the "garbage in, garbage out" problem in the implementation of the IFormattable interface on Int32 type(and possibly on other types as well). The String class does not implement IFormattable, so any format specifier is left unused and .ToString(IFormatProvider) is called instead.
Also:
Ildasm shows that Int32.ToString(String, INumberFormat) internally calls
string System.Number::FormatInt32(int32,
string,
class System.Globalization.NumberFormatInfo)
But it is the internalcall method (extern implemented somewhere in native code), so Ildasm is of no use if we want to determine the source of the problem.
EDIT - CULPRIT:
After reading the How to see code of method which marked as MethodImplOptions.InternalCall? I've used the source code from Shared Source Common Language Infrastructure 2.0 Release (it is .NET 2.0 but nonetheless) in attempt to find a culprit.
Code for the Number.FormatInt32 is located in the ...\sscli20\clr\src\vm\comnumber.cpp file.
The culprit could be deduced from the default section of the format switch statement of the FCIMPL3(Object*, COMNumber::FormatInt32, INT32 value, StringObject* formatUNSAFE, NumberFormatInfo* numfmtUNSAFE):
default:
NUMBER number;
Int32ToNumber(value, &number);
if (fmt != 0) {
gc.refRetString = NumberToString(&number, fmt, digits, gc.refNumFmt);
break;
}
gc.refRetString = NumberToStringFormat(&number, gc.refFormat, gc.refNumFmt);
break;
The fmt var is 0, so the NumberToStringFormat(&number, gc.refFormat, gc.refNumFmt); is being called.
It leads us to nothing else than to the second switch statement default section in the NumberToStringFormat method, that is located in the loop that enumerates every format string character. It is very simple:
default:
*dst++ = ch;
It just plain copies every character from the format string into the output array, that's how the format string ends repeated in the output.
From one point of view it allows to really use garbage format strings that will output nothing useful, but from other point of view it will allow you to use something like:
String garbageFormatted = (1234 as IFormattable).ToString("0 thousands and ### in thousand",
CultureInfo.CurrentCulture.NumberFormat);
Console.WriteLine(garbageFormatted);
// Writes the "1 thousands and 234 in thousand"
that can be handy in some situations.
Interesting behavior indeed BUT NOT unaccounted for.
Your last example works when
if String.Format("My number is {0:n}!", 10)
but revert to the observed beahvior when
if String.Format("My number is {0:nu}!", 10)`.
This prompts to search about the Standard Numeric Format Specifier article on MSDN where you can read
Standard numeric format strings are used to format common numeric
types. A standard numeric format string takes the form Axx, where:
A is a single alphabetic character called the format specifier. Any
numeric format string that contains more than one alphabetic
character, including white space, is interpreted as a custom numeric
format string. For more information, see Custom Numeric Format
Strings.
The same article explains: if you have a SINGLE letter that is not recognized you get an exception.
Indeed
if String.Format("My number is {0:K}!", 10)`.
throws the FormatException as explained.
Now looking in the Custom Numeric Format Strings chapter you will find a table of eligible letters and their possible mixings, but at the end of the table you could read
Other
All other characters
The character is copied to the result string unchanged.
So I think that you have created a format string that cannot in any way print that number because there is no valid format specifier where the number 10 should be 'formatted'.
No it's not acceptable to place anything you like after the colon. Putting anything other than a recognized format specifier is likely to result in either an exception or unpredictable behaviour as you've demonstrated. I don't think you can expect string.Format to behave consistently when you're passing it arguments which are completely inconsistent with the documented formatting types

C# string format arguments

I know that the following syntax works
String.Format("Today is {0}, {1}", day,month);
I was just curious how this format works?
String.Format("Today is {day}, {month}", day,month);
How does C# interpret replacing number with user defined names?
String.Format("Today is {day}, {month}", day,month);
Does not work, it throws a System.FormatException.
According to the documentation the replacement fields must be in the format { index[,alignment][:formatString]} which your 2nd example does not follow.
The items in the {} must be integers beginning at 0 and match the number of variables in the second argument of .Format(...) method. Download a program, such as LinqPad, to run test scripts such as this.

Checking empty text boxes which convert strings to integers using "int.Parse" method in C#

How do I check the empty check boxes which convert strings to integers using "int.Parse" in C#?
If I try to pass blank text boxes, visual studio gives me this error - "Input string was not in a correct format."
I already read some questions on stackoverflow which address the same issue, but I know that various people use various methods to do the same task. So I would like to know them as well. Please start with the simplest way you know first.
int multiplyBy;
if(int.TryParse(textBox3.Text, out multiplyBy)) {
//success
} else {
//string was not in correct format
}
The int.TryParse(string s, out int result) method trys to parse the string, but throws no exception if the format is wrong, it returns a bool indicating if the format was valid. The out int result parameter is the int wich should get the value.
Use Int32.TryParse to verify that the value in the text box is a valid integer
http://msdn.microsoft.com/en-us/library/f02979c7.aspx
You can check if the textbox has a value with:
string.IsNullOrEmpty(textbox.Text)
if you want it in single line of code
vb.net
int i = If(String.IsNullOrEmpty(TextBox1.Text), 0, Int32.Parse(TextBox1.Text))
c#
int i = (String.IsNullOrEmpty(TextBox1.Text)) ?? 0: Int32.Parse(TextBox1.Text)
Instead of directly parsing string representation into integer, check whether it is able to convert in integer. .NET has TryParse method of integer which tries to convert the string representation into int , and returns the bool value indicates whether the conversion succeeded. And if succeeded, stores the parsed value in second parameter of TryParse function which is of out type.
Note: TryParse method does not throw an exception if the conversion fails. It simply returns false indicates that conversion is got failed.
Ref : http://msdn.microsoft.com/en-us/library/f02979c7.aspx
Why don't you just catch the exception
try
{
int multiplyBy = int.Parse(textBox3.Text);
} catch(Exception){}
You can also catch(FormateException) if you like.
Hope this helps!

Compiler Error Message: Cannot implicitly convert type 'long' to 'string'

I have a issue in convertion. Whate is wrong with this conversion?
Here is the error:
Compilation Error Description: An
error occurred during the compilation
of a resource required to service this
request. Please review the following
specific error details and modify your
source code appropriately.
Compiler Error Message: CS0029: Cannot
implicitly convert type 'long' to
'string'
if (hid_Action.Value.ToString().ToUpper() == "RENEW")
{
string strHFUpdate = string.Empty;
string srt = Convert.ToInt64(Session["AppId"] + ",'" + Session["CAAID"].ToString() + "','" + Session["UserType"].ToString() + "'");
strHFUpdate = "oea_sp_update_HF_MC_Renewal_Status " + srt;
rProxy.GlobalSaveData(Session["CountyName"].ToString().Trim(), strHFUpdate.ToString());
}
Appreciate your help!
string srt = Convert.ToInt64(...);
Yes, that cannot work. Hard to guess what was intended here, maybe a missing parenthesis.
Here is the problem
string srt = Convert.ToInt64
You are trying to assign a long value to a string. You can't. You have to use .ToString() to change it into a string, then you will be able to assign.
And one more error, Convert.ToInt64 doesn't convert number with float points, meaning 1.1 will throw an exception. An the string you are trying to convert is totally invalid, what was it supposed to do?
You can't convert a string with commas and single-quotes into a number, additionally, both ToInt64() overloads take a second parameter:
Your code above is trying to implicitly cast the string into another data-type that ToInt64() can take for an overload with a single parameter. ToInt64() does support converting from string but both those overloads take two parameters (see below)
[ From MSDN: http://msdn.microsoft.com/en-us/library/system.convert.toint64.aspx ]
ToInt64(String,
IFormatProvider) Converts the
specified string representation of a
number to an equivalent 64-bit signed
integer, using the specified
culture-specific formatting
information.
ToInt64(String, Int32) Converts the
string representation of a number in a
specified base to an equivalent 64-bit
signed integer.
But as I mentioned, even if you did use the correct overloaded function, your string would not be parse-able due to the non-numeric characters.

Categories