I know that it may sound like a weird question but this has been going on in my mind for a while.
I know that the System.String type in C# is actually a class with a constructor that has a character array parameter. For example the following code is legal and causes no error:
System.String s = new System.String("Hello".toCharArray());
My question is that what makes is possible for the System.String class to accept an array of characters simply this way:
System.String s = "Hello";
When you call:
System.String s = new System.String("Hello".toCharArray());
You are explicitly invoking a constructor
When you write:
string foo = "bar";
An IL instruction (Ldstr) pushes a new object reference to that string literal. It's not the same as calling a constructor.
This is possible because the C# language specifies that string literals are possible (see §2.4.4.5 String literals). The C# compiler and CIL/CLR have good support for how these literals are used, e.g. with the ldstr opcode.
There is no support for including such literals for your own custom types.
Strings are kind of a special clr type. They are the only immutable reference type.
Here are several things which may help you to understand string type:
var a = "Hello";
var b = new String("Hello".ToCharArray());
var c = String.Intern(b); // 'interns' the string...
var equalsString = a == b; // true
var equalsObj = (object)a == (object)b; // false
var equalsInterned = (object)a == (object)c; // true !!
a[0] = 't'; // not valid, because a string is immutable. Instead, do it this way:
var array = b.ToArray();
array[0] = 't';
a = new String(array); // a is now "tello"
Related
Why does the first line compile and the second not?
string var = "123";
var string = "123";
I mean string and var should be both keywords..
var is a contextual keyword, whereas string is not.
Contextual keywords are
used to provide a specific meaning in the code, but it is not a reserved word in C#.
This is why you can use var as a variable name.
Presumably, this is for backwards compatibility. If var were introduced as a proper keyword, old code that uses var as a variable name would break.
I'm trying to convert a json string to a string array
my json string: "[\"false\",\"true\"]"
var js = new System.Web.Script.Serialization.JavaScriptSerializer();
string[] strArray = new string[2];
strArray = js.Deserialize("[\"false\",\"true\"]", string[2]).ToArray();
but it only allows me to do a charArray.
I just need to be able to call my result as strArray[0] so that it will return "false"
Try doing:
strArray = js.Deserialize<string[]>("[\"false\",\"true\"]");
Your example code wouldn't compile. The second parameter should be a Type object, which string[2] isn't. It should be this:
strArray = js.Deserialize("[\"false\",\"true\"]", typeof(string[]));
Or, as the other answer mentioned, you can use the other, generic overload for the method:
strArray = js.Deserialize<string[]>("[\"false\",\"true\"]");
Either one will do exactly the same thing. It's just handy to be able to pass a Type object sometimes if you don't know beforehand what the actual type will be. In this case you do, so it doesn't matter.
Why not use Newtonsoft's JArray type? It is built for this conversion and can handle many edge cases automatically.
var jArray = JArray.Parse("[\"false\",\"true\"]");
var strArray = jArray.ToObject<string[]>()
This will give you a string array. But you could also elect to use .ToArray() to convert to a JToken array which can sometimes be more useful.
I'm writing a plugin for Autodesk Navisworks, trying to pass a C# unicode string to a property on a COM object. However, the string is encoded incorrectly somewhere in the process.
var property = ...;
property.Name = "中文"; // becomes "??"
property.Value = "中文"; // OK
"中文" comes out as "??" in the user interface, whereas strings limited to ASCII work just fine (e.g. "abcd"). Furthermore, setting the Value-property (a VARIANT) on the same object works just fine, but not the Name.
Further exploration leads me to try encoding the string "ä" as utf-8:
C3 A4
and somehow "encoding" this into a (unicode) string:
property.Name = "\u00c3\u00a4"; // shows up as "ä"
Surprisingly this seemed to work.
This led me to try the following:
var bytes = Encoding.UTF8.GetBytes("中文abcd");
char[] chars = new char[bytes.Length];
for(int i = 0; i < chars.Length; i++)
chars[i] = (char)bytes[i];
string s = new string(chars);
However, when I use this trying to encode "中文abcd" I only get the first character "中" in the GUI. Yet, with "äabcd" I get more than one character again...
What is happening here? How can I get around the problem? Is it a marshalling problem (e.g. incorrectly specified encoding in the COM Interop)? Or perhaps some weird code inside the application? If it's a marshalling problem, can I modify it for this property only?
Turns out that Name was an "internal" string, and I should have used the property UserName for text displayed in the GUI.
I.e. I changed:
var property = ...;
property.Name = "中文"; // becomes "??"
property.Value = "中文"; // OK
to this:
var property = ...;
property.UserName = "中文"; // OK!
property.Value = "中文"; // OK
which worked. Presumably UserName is implicitly set from Name internally in some way ignoring or mishandling the encoding.
In PHP I can do the following:
$name = 'John';
$var = "Hello {$name}"; // => Hello John
Is there a similar language construct in C#?
I know there is String.Format(); but I want to know if it can be done without calling a function/method on the string.
In C# 6 you can use string interpolation:
string name = "John";
string result = $"Hello {name}";
The syntax highlighting for this in Visual Studio makes it highly readable and all of the tokens are checked.
This functionality is not built-in to C# 5 or below.
Update: C# 6 now supports string interpolation, see newer answers.
The recommended way to do this would be with String.Format:
string name = "Scott";
string output = String.Format("Hello {0}", name);
However, I wrote a small open-source library called SmartFormat that extends String.Format so that it can use named placeholders (via reflection). So, you could do:
string name = "Scott";
string output = Smart.Format("Hello {name}", new{name}); // Results in "Hello Scott".
Hope you like it!
Use the following methods
1: Method one
var count = 123;
var message = $"Rows count is: {count}";
2: Method two
var count = 123;
var message = "Rows count is:" + count;
3: Method three
var count = 123;
var message = string.Format("Rows count is:{0}", count);
4: Method four
var count = 123;
var message = #"Rows
count
is:{0}" + count;
5: Method five
var count = 123;
var message = $#"Rows
count
is: {count}";
Up to C#5 (-VS2013) you have to call a function/method for it. Either a "normal" function such as String.Format or an overload of the + operator.
string str = "Hello " + name; // This calls an overload of operator +.
In C#6 (VS2015) string interpolation has been introduced (as described by other answers).
I saw this question and similar questions and I preferred to use a built-in method for the problem of using a dictionary of values to fill-in placeholders in a template string. Here's my solution, which is built on the StringFormatter class from this thread:
public static void ThrowErrorCodeWithPredefinedMessage(Enums.ErrorCode errorCode, Dictionary<string, object> values)
{
var str = new StringFormatter(MSG.UserErrorMessages[errorCode]) { Parameters = values};
var applicationException = new ApplicationException($"{errorCode}", new ApplicationException($"{str.ToString().Replace("#","")}"));
throw applicationException;
}
where the message exists in a Dictionary that is not in the caller, but the caller only has access to Enums.ErrorCode, and can build an argument array and send it to the above method as argument.
assuming we have the value of MSG.UserErrorMessages[errorCode] is originally
"The following entry exists in the dump but is not found in #FileName: #entryDumpValue"
The result of this call
var messageDictionary = new Dictionary<string, object> {
{ "FileName", sampleEntity.sourceFile.FileName}, {"entryDumpValue", entryDumpValue }
};
ThrowErrorCodeWithPredefinedMessage(Enums.ErrorCode.MissingRefFileEntry, messageDictionary);
is
The following entry exists in the dump but is not found in cellIdRules.ref: CellBand = L09
The only restriction to this approach is to avoid using '#' in the contents of any of the passed values.
you can define a variable as string like this in C#
var varName= data.Values["some var"] as string;
How I set new value for an string by index value?
I tried:
string a = "abc";
a[0] = "A";
not works for strings, but yes for chars. Why?
Strings in C# (and other .NET languages which use System.String in the base class library) are immutable. That is, you can't modify a string character by character that way (or for that matter, can you modify a string ever).
If you want to modify a string based on the index, you have to convert it to an array using System.String.ToCharArray() first. You convert it back to a string using System.String's constructor, passing in the modified array.
Your example would have to be changed to look like:
string a = "abc";
char[] array = a.ToCharArray();
array[0] = 'A'; //Note single quotes, not double quotes
a = new string(array);
The System.String type does not permit writing by index (or via any means -- to change a the content of a String variable, one must replace it with a reference to an entirely new String). The System.Text.StringBuilder type does, however, permit writing by index. One may create a new System.Text.StringBuilder object (optionally passing a string to the constructor), manipulate it, and then use its ToString method to convert it back to a string.
A replacement would be this:
string a = "abc";
a = a.Remove(0, 1);
a = a.Insert(0, "A");
or for the C say:
string a = "abc";
a = a.Remove(2, 1);
a = a.Insert(2, "C");
Also using a stringbuilder may work as per http://msdn.microsoft.com/en-us/library/362314fe.aspx
StringBuilder sb = new StringBuilder("abc");
sb[0] = 'A';
sb[2] = 'C';
string str = sb.ToString();
Use StringBuilder if you need a mutable String.
Also: a[0] can represent one character while "A" is a String object-it is illegal.
a[0] for a character is a address in memory to which you can assign a value.
string on the other hand is a class and in this case the a[0] is actually a function call to the overloaded operator[]. You can't assign values to functions.