I've encountered some rather bizzar exception while constructing connection string in my application.
string basis = "Data Source={0};Initial Catalog={1};Persist Security Info={2};User ID={3};Password={4}";
List<string> info1 = new List<string>(){ "SQLSRV", "TEST", "True", "user1", "pass1" };
string[] info2 = new string[] { "SQLSRV", "TEST", "True", "user1", "pass1" };
// throws exception
Console.WriteLine(String.Format(basis, info1));
// works fine
Console.WriteLine(String.Format(basis, info2));
Error:
An unhandled exception of type 'System.FormatException' occurred in mscorlib.dll
Additional information: Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
My question is: what is wrong with List's index?
This has nothing to do with the index. In your first case you use this overload of String.Format:
public static void Format(string format, object arg);
and in the second you use this:
public static void Format(string format, params object[] args);
So in the first case you only pass one argument. That leads to an exception because your format string expects more than one argument.
In the second case you provide all arguments because an array instead of only one List object is passed.
It sees the list as a single parameter. The array is seen as the params object[] ... parameter, giving multiple parameter values.
The problem is in the declaration of the String.Format method: The first takes String Format(String format, object arg0), while the second takes string Format(String format, params object[] args).
That makes the first one fail, since it expects more indexed than you supply.
The Method string.Format() accepts an object[] as parameter to replace the placeholder of the format string.
List is not an Array so it is treated as a single object. Which therefore causes the exception because you are providing less parameters than placeholders in your format string.
As you can see from MSDN
https://msdn.microsoft.com/en-us/library/b1csw23d(v=vs.110).aspx
public static string Format( string format, params object[] args )
String.Format wants array: params object[] args as the second parameter, and when you provide a List<String> the entire list has been treated as the 1st item of the array of objects and so the Format fails (you have to provide five items). The easiest remedy is, IMHO, obtain an array via Linq:
Console.WriteLine(String.Format(basis, info1.ToArray()));
Related
I saw some code from a C# Console Application that can pass a string-valued parameter . My question is how can I create my own parametered method?
For example, the following code will pass the parameter value to {0} and print the string with value of Leonel.
Console.Write("{0}", "Leonel");
How can I make a method that can pass a parameter value to string format and return a parameterize string?
public string Combine(string format, params object[] args)
{
var parameterize = //("{0}", args) //I need something like this.
return parameterize;
}
I'm not totally clear on what you're asking, but would calling string.Format work?
string str = string.Format("The value is: {0}", val);
That should call the same underlying function as Console.Write does. It returns the string that would otherwise be printed to the Console. Given that, you probably don't even want your Combine method, as string.Format would take its place.
You can use the static method
string.Format(string str, params string[] formatters);
with your example:
public string Combine(string format, params object[] args)
{
var parameterize = string.Format(format, args);
return parameterize;
}
I'm putting a concatenated string into the Tag property of a component this way:
Tag = String.Format("{0};{1};{2}", AThis, AThat, ATheOtherThing);
Now how do I get it out, as Tag is an object? Trying to do this:
String[] someStuff = Tag.Split(';');
I get, "'object' does not contain a definition for 'Split' and no extension method 'Split' accepting a first argument of type 'object' could be found
The type of Tag is object but the Split method is on String. You need to cast Tag back to String in order to call Split
string[] someStuff = ((string)Tag).Split(';');
As object can be cast to and from any other data type, you can skip the string.Format() completely, and assign a string[]
Tag = new string[] { AThis, AThat, ATheOtherThing };
and
string[] someStuff = (string[])Tag;
or use object[] if AThis, AThat, ATheOtherThing are different data types.
Unless you have some driving need for it as a string another way would be a struct that held your three values, then just set tag to it, and to get it back cast it. No more formating and splitting then. More importantly if you add a fourth item, refactor the struct, job done.
A safe way to convert the Tag back to string is to use the as keyword. If the Tag contains something else than a string it does not throw an exception but returns null
string s = Tag as string;
string[] someStuff = null;
if (s != null) {
someStuff = s.Split(';');
}
As is described at Microsoft Site ,String.Format arranges some String Variables into a single String and is another way how to concate string's in c#.
string.Format("Name = {0} Surname = {1}",name,surname);
My question is how does this work ?
Is this method a Special method ,and can i create a method similar to this one which accepts at every {n} only an Integer .
Or is this method interpreted in a different way by compiler ,if yes than how does the compiler accesses this method .
If it's possible i would like to see ,how does the compiler interpret this Method.
PS : How does it work ,when you can send as much parameters as you want to a method ?
[EDIT]
Does it mean ,that String.Format takes the first Parameter and filter's into with a Regex or Whatever tool (Split etc) to get where {Number} is and places there a String token from second params portion ?
Sending a variable number of parameters to a method is done like this:
public static string MyStringFormat(string formatString, params object [] args)
{
}
You can now pass as many parameters as you like to this:
MyStringFormat("{0}{1}",42,"Hello World")
MyStringFormat("{0}{1}{2}",42,"Hello World",999.9)
Within the method, these arguments are simply an array (of object in this case).
here are the docs on the params keyword.
As for writing you own method to accept numeric input like Format does, this would be one way (using regular expressions):
public static string MyStringFormat(string formatString, params object[] args)
{
var regex = new Regex("{([0-9]*)}");
return regex.Replace(formatString,m =>
{
int index = int.Parse(m.Groups[1].Value);
if(index<args.Length)
return args[index].ToString();
return String.Empty;
});
}
Live example: http://rextester.com/rundotnet?code=OMZC13551
It is a normal function.
It parses the string and calls ToString on the incoming parameters (if needed) in order to construct the new string.
The signature of the overload you have in your example is:
public static string Format(
string format,
params Object[] args
)
There is nothing to stop you from creating your own (though I would probably just delegate to the built in string.Format).
Use params: http://msdn.microsoft.com/en-us/library/w5zay9db.aspx
there is no magic there Cody, look at this method:
public static void UseParams(params int[] list)
{
for (int i = 0 ; i < list.Length; i++)
{
Console.WriteLine(list[i]);
}
Console.WriteLine();
}
you can call it passing as many int you like, it's the params parameter type :)
Edit:
params is very useful it allows us, for example, to pass to our logging wrapper all method's parameters values in a dynamic way without knowing how many of them each method has, the logger will then dump all those values one by one using Reflection to find out the parameter name as well.
The braces in the string are placeholders and a number within that denotes the index of argument it is to be replaced with.
Format is of type (string format, params object[] args) and it is the index in this object[] which is helpful.
(I think it internally uses the StringBuilder.AppendFormat) for substituting those values)
The signature of String.Format looks like this:
public static string Format (string format, params Object[] args)
Note the second parameter, marked with the params keyword. That one provides the functionality to add multiple parameters when calling the function. Inside the function you can access the parameters by index or iterating over args array:
public static string Format (string format, params Object[] args)
{
foreach (Object o in args)
Console.WriteLine(o);
}
Have a look at the C# Reference.
Where can I get info about implementing my own methods that have the ellipsis notation,
e.g.
static void my_printf(char* format, ...) { }
Also is that called ellipsis notation or is there a fancier name?
Have a look at the params keyword
From https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/params:
By using the params keyword, you can specify a method parameter that
takes a variable number of arguments.
You can send a comma-separated list of arguments of the type specified
in the parameter declaration or an array of arguments of the specified
type. You also can send no arguments. If you send no arguments, the
length of the params list is zero.
static void MyPrintf(string format, params object[] args) { }
...
MyPrintf(1, 'a', "test");
I"m developing a simple application that have a line like this:
string[] values = ReadAll(inputFile);
As inputFile is a string, but how I can do this without conflicts(Cannot implicitly convert type 'string' in 'string[]')?
Assuming your ReadAll method has a signature like this
string ReadAll(string inputFile);
then the problem is not with inputFile but with the return value of the method which cannot be assigned to a string[].
Are you maybe looking for File.ReadAllLines?
string[] values = File.ReadAllLines(inputFile);
Or do you want to split a string by some delimeter?
string[] values = ReadAll(inputFile).Split('\n');
Based on the exception message you gave us, ReadAll(inputFile) returns a string, and you assign it to a string[], so that's why it doesn't work.
This would work:
string input = ReadAll(inputFile);
After this do you want to split the strings in some way? We'd need more details to help you further.