What's does the dollar sign ($"string") do? [duplicate] - c#

This question already has answers here:
What does $ mean before a string?
(11 answers)
Closed 6 years ago.
I have been looking over some C# exercises in a book and I ran across an example that stumped me. Straight from the book, the output line shows as:
Console.WriteLine($"\n\tYour result is {result}.");
The code works and the double result shows as expected. However, not understanding why the $ is there at the front of the string, I decided to remove it, and now the code outputs the name of the array {result} instead of the contents. The book doesn't explain why the $ is there, unfortunately.
I have been scouring the VB 2015 help and Google, regarding string formatting and Console.WriteLine overload methods. I am not seeing anything that explains why it is what it is. Any advice would be appreciated.

It's the new feature in C# 6 called Interpolated Strings.
The easiest way to understand it is: an interpolated string expression creates a string by replacing the contained expressions with the ToString representations of the expressions' results.
For more details about this, please take a look at MSDN.
Now, think a little bit more about it. Why this feature is great?
For example, you have class Point:
public class Point
{
public int X { get; set; }
public int Y { get; set; }
}
Create 2 instances:
var p1 = new Point { X = 5, Y = 10 };
var p2 = new Point { X = 7, Y = 3 };
Now, you want to output it to the screen. The 2 ways that you usually use:
Console.WriteLine("The area of interest is bounded by (" + p1.X + "," + p1.Y + ") and (" + p2.X + "," + p2.Y + ")");
As you can see, concatenating string like this makes the code hard to read and error-prone. You may use string.Format() to make it nicer:
Console.WriteLine(string.Format("The area of interest is bounded by({0},{1}) and ({2},{3})", p1.X, p1.Y, p2.X, p2.Y));
This creates a new problem:
You have to maintain the number of arguments and index yourself. If the number of arguments and index are not the same, it will generate a runtime error.
For those reasons, we should use new feature:
Console.WriteLine($"The area of interest is bounded by ({p1.X},{p1.Y}) and ({p2.X},{p2.Y})");
The compiler now maintains the placeholders for you so you don’t have to worry about indexing the right argument because you simply place it right there in the string.
For the full post, please read this blog.

String Interpolation
is a concept that languages like Perl have had for quite a while, and
now we’ll get this ability in C# as well. In String Interpolation, we
simply prefix the string with a $ (much like we use the # for verbatim
strings). Then, we simply surround the expressions we want to
interpolate with curly braces (i.e. { and }):
It looks a lot like the String.Format() placeholders, but instead of an index, it is the expression itself inside the curly braces. In fact, it shouldn’t be a surprise that it looks like String.Format() because that’s really all it is – syntactical sugar that the compiler treats like String.Format() behind the scenes.
A great part is, the compiler now maintains the placeholders for you so you don’t have to worry about indexing the right argument because you simply place it right there in the string.
C# string interpolation is a method of concatenating,formatting and manipulating strings. This feature was introduced in C# 6.0. Using string interpolation, we can use objects and expressions as a part of the string interpolation operation.
Syntax of string interpolation starts with a ‘$’ symbol and expressions are defined within a bracket {} using the following syntax.
{<interpolatedExpression>[,<alignment>][:<formatString>]}
Where:
interpolatedExpression - The expression that produces a result to be formatted
alignment - The constant expression whose value defines the minimum number of characters in the string representation of the
result of the interpolated expression. If positive, the string
representation is right-aligned; if negative, it's left-aligned.
formatString - A format string that is supported by the type of the expression result.
The following code example concatenates a string where an object, author as a part of the string interpolation.
string author = "Mohit";
string hello = $"Hello {author} !";
Console.WriteLine(hello); // Hello Mohit !
Read more on C#/.NET Little Wonders: String Interpolation in C# 6

Related

c# xml SelectSingleNode issue unable to use variable in node name

Have the following line of code
// Load screen containers
serverTest = document.SelectSingleNode("Server/". this.serverName . "/test").InnerText;
C# isn't liking the "." concatenation character, not sure what to do here.
serverTest is a property of my class btw
Oops was using PHP concatenation character, was using that language an hour ago.
Could one of the mods delete this one, sorry for taking up space.
You have to do something like this.
document.SelectSingleNode(#"Server/" + this.serverName + #"/test").InnerText;
For string concatenation, use the "+" plus operator or maybe string.Format if it contains a lot of variables
document.SelectSingleNode(#"Server/" + this.serverName + #"/app").InnerText;
For lots of variables (multiple parameters may be usable once you require attribute based retrieval of nodes):-
// for [Server/localhost/App/MyApp/Module/Admin/Action/Test"
var location = string.Format(#"Server/{0}/App/{1}/Module/{2}/Action/{3}", this.serverName, this.appName, this.moduleName, this.actionName);
document.SelectSingleNode(location).InnerText;
By separating the location from the retrieval function, you can easily debug it and log in case any value is improper. Also makes code readable IMHO.
However for a single value, using concatenation inline can be ok in most cases.

Outputting c# console application to webpage [duplicate]

Is there an easy way to create a multiline string literal in C#?
Here's what I have now:
string query = "SELECT foo, bar"
+ " FROM table"
+ " WHERE id = 42";
I know PHP has
<<<BLOCK
BLOCK;
Does C# have something similar?
You can use the # symbol in front of a string to form a verbatim string literal:
string query = #"SELECT foo, bar
FROM table
WHERE id = 42";
You also do not have to escape special characters when you use this method, except for double quotes as shown in Jon Skeet's answer.
It's called a verbatim string literal in C#, and it's just a matter of putting # before the literal. Not only does this allow multiple lines, but it also turns off escaping. So for example you can do:
string query = #"SELECT foo, bar
FROM table
WHERE name = 'a\b'";
This includes the line breaks (using whatever line break your source has them as) into the string, however. For SQL, that's not only harmless but probably improves the readability anywhere you see the string - but in other places it may not be required, in which case you'd either need to not use a multi-line verbatim string literal to start with, or remove them from the resulting string.
The only bit of escaping is that if you want a double quote, you have to add an extra double quote symbol:
string quote = #"Jon said, ""This will work,"" - and it did!";
As a side-note, with C# 6.0 you can now combine interpolated strings with the verbatim string literal:
string camlCondition = $#"
<Where>
<Contains>
<FieldRef Name='Resource'/>
<Value Type='Text'>{(string)parameter}</Value>
</Contains>
</Where>";
The problem with using string literal I find is that it can make your code look a bit "weird" because in order to not get spaces in the string itself, it has to be completely left aligned:
var someString = #"The
quick
brown
fox...";
Yuck.
So the solution I like to use, which keeps everything nicely aligned with the rest of your code is:
var someString = String.Join(
Environment.NewLine,
"The",
"quick",
"brown",
"fox...");
And of course, if you just want to logically split up lines of an SQL statement like you are and don't actually need a new line, you can always just substitute Environment.NewLine for " ".
One other gotcha to watch for is the use of string literals in string.Format. In that case you need to escape curly braces/brackets '{' and '}'.
// this would give a format exception
string.Format(#"<script> function test(x)
{ return x * {0} } </script>", aMagicValue)
// this contrived example would work
string.Format(#"<script> function test(x)
{{ return x * {0} }} </script>", aMagicValue)
Why do people keep confusing strings with string literals? The accepted answer is a great answer to a different question; not to this one.
I know this is an old topic, but I came here with possibly the same question as the OP, and it is frustrating to see how people keep misreading it. Or maybe I am misreading it, I don't know.
Roughly speaking, a string is a region of computer memory that, during the execution of a program, contains a sequence of bytes that can be mapped to text characters. A string literal, on the other hand, is a piece of source code, not yet compiled, that represents the value used to initialize a string later on, during the execution of the program in which it appears.
In C#, the statement...
string query = "SELECT foo, bar"
+ " FROM table"
+ " WHERE id = 42";
... does not produce a three-line string but a one liner; the concatenation of three strings (each initialized from a different literal) none of which contains a new-line modifier.
What the OP seems to be asking -at least what I would be asking with those words- is not how to introduce, in the compiled string, line breaks that mimick those found in the source code, but how to break up for clarity a long, single line of text in the source code without introducing breaks in the compiled string. And without requiring an extended execution time, spent joining the multiple substrings coming from the source code. Like the trailing backslashes within a multiline string literal in javascript or C++.
Suggesting the use of verbatim strings, nevermind StringBuilders, String.Joins or even nested functions with string reversals and what not, makes me think that people are not really understanding the question. Or maybe I do not understand it.
As far as I know, C# does not (at least in the paleolithic version I am still using, from the previous decade) have a feature to cleanly produce multiline string literals that can be resolved during compilation rather than execution.
Maybe current versions do support it, but I thought I'd share the difference I perceive between strings and string literals.
UPDATE:
(From MeowCat2012's comment) You can. The "+" approach by OP is the best. According to spec the optimization is guaranteed: http://stackoverflow.com/a/288802/9399618
Add multiple lines : use #
string query = #"SELECT foo, bar
FROM table
WHERE id = 42";
Add String Values to the middle : use $
string text ="beer";
string query = $"SELECT foo {text} bar ";
Multiple line string Add Values to the middle: use $#
string text ="Customer";
string query = $#"SELECT foo, bar
FROM {text}Table
WHERE id = 42";
You can use # and "".
string sourse = #"{
""items"":[
{
""itemId"":0,
""name"":""item0""
},
{
""itemId"":1,
""name"":""item1""
}
]
}";
In C# 11 [2022], you will be able to use Raw String literals.
The use of Raw String Literals makes it easier to use " characters without having to write escape sequences.
Solution for OP:
string query1 = """
SELECT foo, bar
FROM table
WHERE id = 42
""";
string query2 = """
SELECT foo, bar
FROM table
WHERE id = 42
and name = 'zoo'
and type = 'oversized "jumbo" grand'
""";
More details about Raw String Literals
See the Raw String Literals GitHub Issue for full details; and Blog article C# 11 Preview Updates – Raw string literals, UTF-8 and more!
I haven't seen this, so I will post it here (if you are interested in passing a string you can do this as well.) The idea is that you can break the string up on multiple lines and add your own content (also on multiple lines) in any way you wish. Here "tableName" can be passed into the string.
private string createTableQuery = "";
void createTable(string tableName)
{
createTableQuery = #"CREATE TABLE IF NOT EXISTS
["+ tableName + #"] (
[ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[Key] NVARCHAR(2048) NULL,
[Value] VARCHAR(2048) NULL
)";
}
Yes, you can split a string out onto multiple lines without introducing newlines into the actual string, but it aint pretty:
string s = $#"This string{
string.Empty} contains no newlines{
string.Empty} even though it is spread onto{
string.Empty} multiple lines.";
The trick is to introduce code that evaluates to empty, and that code may contain newlines without affecting the output. I adapted this approach from this answer to a similar question.
There is apparently some confusion as to what the question is, but there are two hints that what we want here is a string literal not containing any newline characters, whose definition spans multiple lines. (in the comments he says so, and "here's what I have" shows code that does not create a string with newlines in it)
This unit test shows the intent:
[TestMethod]
public void StringLiteralDoesNotContainSpaces()
{
string query = "hi"
+ "there";
Assert.AreEqual("hithere", query);
}
Change the above definition of query so that it is one string literal, instead of the concatenation of two string literals which may or may not be optimized into one by the compiler.
The C++ approach would be to end each line with a backslash, causing the newline character to be escaped and not appear in the output. Unfortunately, there is still then the issue that each line after the first must be left aligned in order to not add additional whitespace to the result.
There is only one option that does not rely on compiler optimizations that might not happen, which is to put your definition on one line. If you want to rely on compiler optimizations, the + you already have is great; you don't have to left-align the string, you don't get newlines in the result, and it's just one operation, no function calls, to expect optimization on.
If you don't want spaces/newlines, string addition seems to work:
var myString = String.Format(
"hello " +
"world" +
" i am {0}" +
" and I like {1}.",
animalType,
animalPreferenceType
);
// hello world i am a pony and I like other ponies.
You can run the above here if you like.
using System;
namespace Demo {
class Program {
static void Main(string[] args) {
string str = #"Welcome User,
Kindly wait for the image to
load";
Console.WriteLine(str);
}
}
}
Output
Welcome User,
Kindly wait for the image to
load

String.Contains and String.LastIndexOf C# return different result?

I have this problem where String.Contains returns true and String.LastIndexOf returns -1. Could someone explain to me what happened? I am using .NET 4.5.
static void Main(string[] args)
{
String wikiPageUrl = #"http://it.wikipedia.org/wiki/ʿAbd_Allāh_al-Sallāl";
if (wikiPageUrl.Contains("wikipedia.org/wiki/"))
{
int i = wikiPageUrl.LastIndexOf("wikipedia.org/wiki/");
Console.WriteLine(i);
}
}
While #sa_ddam213's answer definitely fixes the problem, it might help to understand exactly what's going on with this particular string.
If you try the example with other "special characters," the problem isn't exhibited. For example, the following strings work as expected:
string url1 = #"http://it.wikipedia.org/wiki/»Abd_Allāh_al-Sallāl";
Console.WriteLine(url1.LastIndexOf("it.wikipedia.org/wiki/")); // 7
string url2 = #"http://it.wikipedia.org/wiki/~Abd_Allāh_al-Sallāl";
Console.WriteLine(url2.LastIndexOf("it.wikipedia.org/wiki/")); // 7
The character in question, "ʿ", is called a spacing modifier letter1. A spacing modifier letter doesn't stand on its own, but modifies the previous character in the string, this case a "/". Another way to put this is that it doesn't take up its own space when rendered.
LastIndexOf, when called with no StringComparison argument, compares strings using the current culture.
When strings are compared in a culture-sensitive manner, the "/" and "ʿ" characters are not seen as two distinct characters--they're processed into one character, which does not match the parameter passed in to LastIndexOf.
When you pass in StringComparison.Ordinal to LastIndexOf, the characters are treated as distinct, due to the nature of Ordinal comparison.
Another way to make this work would be to use CompareInfo.LastIndexOf and supply the CompareOptions.IgnoreNonSpace option:
Console.WriteLine(
CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(
wikiPageUrl, #"it.wikipedia.org/wiki/", CompareOptions.IgnoreNonSpace));
// 7
Here we're saying that we don't want combining characters included in our string comparison.
As a sidenote, this means that #Partha's answer and #Noctis' answer only work because the character is being applied to a character that doesn't appear in the search string that's passed to LastIndexOf.
Contrast this with the Contains method, which by default performs an Ordinal (case sensitive and culture insensitive) comparison. This explains why Contains returns true and LastIndexOf returns false.
For a fantastic overview of how strings should be manipulated in the .NET framework, check out this article.
1: Is this different than a combining character or is it a type of combining character? would appreciate if someone would clear that up for me.
Try using StringComparison.Ordinal
This will compare the string by evaluating the numeric values of the corresponding chars in each string, this should work with the special chars you have in that example string
string wikiPageUrl = #"http://it.wikipedia.org/wiki/ʿAbd_Allāh_al-Sallāl";
int i = wikiPageUrl.LastIndexOf("http://it.wikipedia.org/wiki/", StringComparison.Ordinal);
// returns 0;
The thing is C# lastindexof looks from behind.
And wikipedia.org/wiki/ is followed by ' which it takes as escape sequence. So either remove ' after wiki/ or have an # there too.
The following syntax will work( anyone )
string wikiPageUrl = #"http://it.wikipedia.org/wiki/Abd_Allāh_al-Sallāl";
string wikiPageUrl = #"http://it.wikipedia.org/wiki/#ʿAbd_Allāh_al-Sallāl";
int i = wikiPageUrl.LastIndexOf("wikipedia.org/wiki");
All 3 works
If you want a generalized solution for this problem replace ' with #' in your string before you perform any operations.
the ' characters throws it off.
This should work, when you escape the ' as \':
wikiPageUrl = #"http://it.wikipedia.org/wiki/\'Abd_Allāh_al-Sallāl";
if (wikiPageUrl.Contains("wikipedia.org/wiki/"))
{
"contains".Dump();
int i = wikiPageUrl.LastIndexOf("wikipedia.org/wiki/");
Console.WriteLine(i);
}
figure out what you want to do (remove the ', escape it, or dig deeper :) ).

C# - How can I convert an escaped string into a literal string? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can I expand a string that contains C# literal expressions at runtime
How can I convert an escaped string read from a file at runtime, e.g.
"Line1\nLine2"
into its literal value:
Line1
Line2
Amazingly I have found an example to do the opposite here using CSharpCodeProvider(), which seems like it would be the more difficult conversion. In order to do the opposite it appears I need to generate code to define a class and compile it in memory or execute a series of .Replace() calls, hoping I don't miss any escape sequences.
CSharpCodeProvider sounds like it certainly can do the trick here. However, I would ask 2 questions before using that: is it required to be exactly C# string literal syntax, and is the input file trusted?
CSharpCodeProvider obviously provides exactly the syntax of the C# compiler, but it seems to me like it'd be relatively easy for someone to inject some code into your process via this route.
The Javascript string literal syntax is fairly close to the C# string literal syntax, and .NET includes a JavaScriptSerializer class which can parse such string literals without injecting it as code into the running process.
Replace the escaped value by \n
static void Main(string[] args)
{
var test = "Line1\\nLine2";
// Line1\nLine2
Console.WriteLine(test);
// Line1
// Line2
Console.WriteLine(test.Replace("\\n", Environment.NewLine));
Console.ReadKey();
}

Reverse of String.Format? [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Parsing formatted string.
How can I use a String.Format format and transform its output to its inputs?
For example:
string formatString = "My name is {0}. I have {1} cow(s).";
string s = String.Format(formatString, "strager", 2);
// Call the magic method...
ICollection<string> parts = String.ReverseFormat(formatString, s);
// parts now contains "strager" and "2".
I know I can use regular expressions to do this, but I would like to use the same format string so I only need to maintain one line of code instead of two.
Here is some code from someone attempting a Scanf equivalent in C#:
http://www.codeproject.com/KB/recipes/csscanf.aspx
You'll have to implement it yourself, as there's nothing built in to do it for you.
To that end, I suggest you get the actual source code for the .Net string.format implmentation (actually, the relevant code is in StringBuilder.AppendFormat()). It's freely available, and it uses a state machine to walk the string in a very performant manner. You can mimic that code to also walk your formatted string and extract that data.
Note that it won't always be possible to go backwards. Sometimes the formatted string can have characters the match the format specifiers, making it difficult to impossible for the program to know what the original looked like. As I think about it, you might have better luck walking the original string to turn it into a regular expression, and then use that to do the match.
I'd also recommend renaming your method to InvertFormat(), because ReverseFormat sounds like you'd expect this output:
.)s(woc 2 evah .regarts si eman yM
I don't believe there's anything in-box to support this, but in C#, you can pass an array of objects directly to any method taking params-marked array parameters, such as String.Format(). Other than that, I don't believe there's some way for C# & the .NET Framework to know that string X was built from magic format string Y and undo the merge.
Therefore, the only thing I can think of is that you could format your code thusly:
object[] parts = {"strager", 2};
string s = String.Format(formatString, parts);
// Later on use parts, converting each member .ToString()
foreach (object p in parts)
{
Console.WriteLine(p.ToString());
}
Not ideal, and probably not quite what you're looking for, but I think it's the only way.

Categories

Resources