$ Có nghĩa là gì trước một chuỗi?


250

Tôi sẽ sử dụng chuỗi nguyên văn nhưng tôi gõ nhầm $thay vì @.

Nhưng Trình biên dịch không cung cấp cho tôi bất kỳ Lỗi nào và được biên dịch thành công.

Tôi muốn biết nó là gì và nó làm gì. Tôi đã tìm kiếm nó nhưng tôi không thể tìm thấy bất cứ điều gì.

Tuy nhiên, nó không giống như một chuỗi nguyên văn vì tôi không thể viết:

string str = $"text\";

Có ai biết những gì $trước khi chuỗi đại diện cho C #.

string str = $"text";

Tôi đang sử dụng Visual studio 2015 CTP.

Câu trả lời:


418

$là viết tắt String.Formatvà được sử dụng với nội suy chuỗi, đây là một tính năng mới của C # 6. Như được sử dụng trong trường hợp của bạn, nó không làm gì cả, giống như string.Format()sẽ không làm gì cả.

Nó được sử dụng khi xây dựng các chuỗi có tham chiếu đến các giá trị khác. Những gì trước đây phải được viết là:

var anInt = 1;
var aBool = true;
var aString = "3";
var formated = string.Format("{0},{1},{2}", anInt, aBool, aString);

Bây giờ trở thành:

var anInt = 1;
var aBool = true;
var aString = "3";
var formated = $"{anInt},{aBool},{aString}";

Ngoài ra còn có một hình thức nội suy chuỗi - ít được biết đến - sử dụng $@ (thứ tự của hai ký hiệu là quan trọng). Nó cho phép các tính năng của một @""chuỗi được trộn lẫn $""để hỗ trợ các phép nội suy chuỗi mà không cần \\trong suốt chuỗi của bạn. Vậy hai dòng sau:

var someDir = "a";
Console.WriteLine($@"c:\{someDir}\b\c");

sẽ xuất ra:

c:\a\b\c

29
Lưu ý rằng nó không thực sự sử dụng String.Format, nhưng là một tính năng dựa trên trình biên dịch, không phải là thời gian chạy.
Shahar Prish

2
Lưu ý nhỏ mà tôi đã học ngày hôm nay, nếu bạn sử dụng $@, thì bạn buộc phải thoát khỏi "nhân vật bằng cách sử dụng "". Đây không phải là trường hợp khi bạn chỉ sử dụng $.
Flater

3
@Flater Điều đó không liên quan gì đến biểu tượng $. Đó là hành vi tương tự như trước khi biểu tượng $ tồn tại.
BVernon

2
Theo quan điểm của bạn về thứ tự nguyên văn (@) và thứ tự biểu tượng nội suy ($) là quan trọng, điều này được sửa trong C # 8 để việc đặt hàng sẽ không còn quan trọng nữa. Xem: devsanon.com/unc Classified / từ
elkaz

38

Nó tạo ra một chuỗi nội suy .

Từ MSDN

Được sử dụng để xây dựng chuỗi. Một biểu thức chuỗi được nội suy trông giống như một chuỗi mẫu có chứa các biểu thức. Một biểu thức chuỗi được nội suy tạo ra một chuỗi bằng cách thay thế các biểu thức được chứa bằng các phản hồi ToString của các kết quả của biểu thức.

Ví dụ :

 var name = "Sam";
 var msg = $"hello, {name}";

 Console.WriteLine(msg); // hello, Sam

Bạn có thể sử dụng các biểu thức trong chuỗi nội suy

 var msg = $"hello, {name.ToLower()}";
 Console.WriteLine(msg); // hello, sam

Điều thú vị ở đây là bạn không cần phải lo lắng về thứ tự của các tham số như bạn làm với String.Format.

  var s = String.Format("{0},{1},{2}...{88}",p0,p1,..,p88);

Bây giờ nếu bạn muốn loại bỏ một số tham số bạn phải đi và cập nhật tất cả các số đếm, đó không phải là trường hợp nữa.

Lưu ý rằng cái cũ string.formatvẫn có liên quan nếu bạn muốn chỉ định thông tin văn hóa trong định dạng của bạn .


Lưu ý rằng bạn có thể vẫn có thể sử dụng $và chỉ định thông tin văn hóa nếu bạn chuyển đổi dữ liệu của mình thành chuỗi bên trong $biểu thức bằng cách sử dụng văn hóa chính xác, ví dụ : {somevar.ToString(...,[Insert culture info here])}.
jrh

18

Mã ví dụ

public class Person {
    public String firstName { get; set; }
    public String lastName { get; set; }
}

// Instantiate Person
var person = new Person { firstName = "Albert", lastName = "Einstein" };

// We can print fullname of the above person as follows
Console.WriteLine("Full-Name - " + person.firstName + " " + person.lastName);
Console.WriteLine("Full-Name - {0} {1}", person.firstName, person.lastName);
Console.WriteLine($"Full-Name - {person.firstName} {person.lastName}");

Đầu ra

Full-Name - Albert Einstein
Full-Name - Albert Einstein
Full-Name - Albert Einstein

Đó là Chuỗi nội suy . Bạn có thể sử dụng một chuỗi nội suy ở bất cứ đâu bạn có thể sử dụng một chuỗi ký tự. Khi chạy chương trình của bạn sẽ thực thi mã với chuỗi ký tự được nội suy, mã sẽ tính toán một chuỗi ký tự mới bằng cách đánh giá các biểu thức nội suy. Tính toán này xảy ra mỗi khi mã với chuỗi nội suy thực thi.

Ví dụ sau đây tạo ra một giá trị chuỗi trong đó tất cả các giá trị nội suy chuỗi đã được tính toán. Đây là kết quả cuối cùng và có chuỗi loại. Tất cả các lần xuất hiện của dấu ngoặc nhọn (“{{“ and “}}”)được chuyển thành một dấu ngoặc đơn.

string text = "World";
var message = $"Hello, {text}";

Sau khi thực hiện trên 2 dòng, biến messagechứa "Hello, World".

Console.WriteLine(message); // Prints Hello, World

Tham khảo - MSDN


10

Tính năng mát mẻ. Tôi chỉ muốn chỉ ra sự nhấn mạnh về lý do tại sao điều này tốt hơn string.format nếu nó không rõ ràng với một số người.

Tôi đọc ai đó nói thứ tự string.format thành "{0} {1} {2}" để khớp với các tham số. Bạn không bị buộc phải đặt hàng "{0} {1} {2}" trong chuỗi.format, bạn cũng có thể thực hiện "{2} {0} {1}". Tuy nhiên, nếu bạn có nhiều tham số, như 20, bạn thực sự muốn sắp xếp chuỗi thành "{0} {1} {2} ... {19}". Nếu đó là một mớ hỗn độn, bạn sẽ gặp khó khăn trong việc sắp xếp các thông số của mình.

Với $, bạn có thể thêm tham số nội tuyến mà không cần đếm tham số của mình. Điều này làm cho mã dễ đọc và bảo trì hơn nhiều.

Nhược điểm của $ là, bạn không thể lặp lại tham số trong chuỗi một cách dễ dàng, bạn phải gõ nó. Ví dụ: nếu bạn cảm thấy mệt mỏi khi gõ System.En Môi.NewLine, bạn có thể thực hiện chuỗi.format ("... {0} ... {0} ... {0}", System.En Môi.NewLine), nhưng, bằng $, bạn phải lặp lại nó. Bạn không thể thực hiện $ "{0}" và chuyển nó vào chuỗi.format vì $ "{0}" trả về "0".

Về mặt ghi chú, tôi đã đọc một bình luận trong một tpoic trùng lặp khác. Tôi không thể bình luận, vì vậy, đây là. Anh ấy nói rằng

string msg = n + " sheep, " + m + " chickens";

tạo nhiều hơn một đối tượng chuỗi. Điều này thực sự không đúng. Nếu bạn làm điều này trong một dòng duy nhất, nó chỉ tạo một chuỗi và được đặt trong bộ đệm chuỗi.

1) string + string + string + string;
2) string.format()
3) stringBuilder.ToString()
4) $""

Tất cả chúng trả về một chuỗi và chỉ tạo một giá trị trong bộ đệm.

Mặt khác:

string+= string2;
string+= string2;
string+= string2;
string+= string2;

Tạo 4 giá trị khác nhau trong bộ đệm vì có 4 ";".

Do đó, việc viết mã như sau sẽ dễ dàng hơn, nhưng bạn sẽ tạo năm chuỗi nội suy khi Carlos Muñoz sửa:

string msg = $"Hello this is {myName}, " +
  $"My phone number {myPhone}, " +
  $"My email {myEmail}, " +
  $"My address {myAddress}, and " +
  $"My preference {myPreference}.";

Điều này tạo ra một chuỗi trong bộ đệm trong khi bạn có mã rất dễ đọc. Tôi không chắc chắn về hiệu suất, nhưng, tôi chắc chắn MS sẽ tối ưu hóa nó nếu chưa làm điều đó.


1
Ví dụ cuối cùng của bạn là sai: Trên thực tế, bạn đang đặt hai chuỗi: Một từ chuỗi nội suy và khác từ các chuỗi còn lại. Lưu ý rằng chỉ có một cái có {myName} được nội suy, những cái khác không hoạt động như mong đợi.
Carlos Muñoz

1
Và nếu bạn trả trước $ cho 5 chuỗi thì nó sẽ tạo ra 5 chuỗi được nội suy với mỗi chuỗi String.Format()và sau đó được nối với nhau trong thời gian chạy với String.Concat. Vì vậy, tốt hơn là bạn không chia nó thành nhiều dòng
Carlos Muñoz

1
Bạn nói đúng @Carlos Muñoz, tôi đã sửa nó. Cảm ơn đã bắt lỗi.
BoBoDev

8

Lưu ý rằng bạn cũng có thể kết hợp cả hai, điều này khá tuyệt (mặc dù trông hơi kỳ lạ):

// simple interpolated verbatim string
WriteLine($@"Path ""C:\Windows\{file}"" not found.");

5
Nếu chỉ bạn có thể quyết định thứ tự mà bạn gõ $@hoặc @$. Thật không may, nó chỉ có thể là$@
Bauss

2
@Bauss Điều này có ý nghĩa. @định nghĩa làm thế nào để biểu diễn chuỗi ký tự. $là một phím tắt cho string.Format. Hãy nghĩ về nó như$(@"");
soái ca

Nó không thực sự là một phím tắt cho string.Format. Đó là đường để trình bày một giá trị được phân tích cú pháp cho một string.Format, vì vậy nó một phần có ý nghĩa, nhưng không hoàn toàn.
Bauss

3
Tôi chỉ nói $về cơ bản là một hàm gọi hàm trong khi đó @là một phần của nghĩa đen, giống như mtrong một chữ thập phân. Đó là lý do tại sao chỉ có một thứ tự hợp lý.
soái ca

2
Tôi biết điều này chủ yếu chỉ ở đây để chứng minh $, nhưng vì mục đích tương thích tối đa và không khó mã hóa cho dù dấu phân cách thư mục là '/' hay '\', và cũng tránh việc vặn vít không thể tránh khỏi gây ra một dấu gạch chéo kép hoặc thiếu dấu gạch chéo đã là một, tôi khuyên bạn nên sử dụng Path.Combine()thay vì sử dụng nối chuỗi khi làm việc với các thư mục và tệp.
jrh

6

Nó thuận tiện hơn chuỗi.Format và bạn cũng có thể sử dụng intellisense tại đây.

nhập mô tả hình ảnh ở đây

Và đây là phương pháp thử nghiệm của tôi:

[TestMethod]
public void StringMethodsTest_DollarSign()
{
    string name = "Forrest";
    string surname = "Gump";
    int year = 3; 
    string sDollarSign = $"My name is {name} {surname} and once I run more than {year} years."; 
    string expectedResult = "My name is Forrest Gump and once I run more than 3 years."; 
    Assert.AreEqual(expectedResult, sDollarSign);
}

6

Nó biểu thị nội suy chuỗi.

Nó sẽ bảo vệ bạn bởi vì nó đang thêm bảo vệ thời gian biên dịch trên đánh giá chuỗi.

Bạn sẽ không còn có ngoại lệ với string.Format("{0}{1}",secondParamIsMissing)


6

Ví dụ sau đây nêu bật những lợi thế khác nhau của việc sử dụng các chuỗi nội suy trong string.Format()chừng mực độ sạch và dễ đọc. Nó cũng cho thấy mã bên trong {}được đánh giá như bất kỳ đối số chức năng nào khác, giống như khi string.Format()chúng ta được gọi.

using System;

public class Example
{
   public static void Main()
   {
      var name = "Horace";
      var age = 34;
      // replaces {name} with the value of name, "Horace"
      var s1 = $"He asked, \"Is your name {name}?\", but didn't wait for a reply.";
      Console.WriteLine(s1);

      // as age is an integer, we can use ":D3" to denote that
      // it should have leading zeroes and be 3 characters long
      // see https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-pad-a-number-with-leading-zeros
      //
      // (age == 1 ? "" : "s") uses the ternary operator to 
      // decide the value used in the placeholder, the same 
      // as if it had been placed as an argument of string.Format
      //
      // finally, it shows that you can actually have quoted strings within strings
      // e.g. $"outer { "inner" } string"
      var s2 = $"{name} is {age:D3} year{(age == 1 ? "" : "s")} old.";
      Console.WriteLine(s2); 
   }
}
// The example displays the following output:
//       He asked, "Is your name Horace?", but didn't wait for a reply.
//       Horace is 034 years old.

6

$ cú pháp là tốt, nhưng với một nhược điểm.

Nếu bạn cần một cái gì đó giống như một mẫu chuỗi, được khai báo ở cấp độ lớp như trường ... cũng ở một nơi như nó phải vậy.

Sau đó, bạn phải khai báo các biến ở cùng cấp độ ... điều này không thực sự thú vị.

Sử dụng cú pháp chuỗi.Format cho loại điều này sẽ tốt hơn nhiều

class Example1_StringFormat {
 string template = $"{0} - {1}";

 public string FormatExample1() {
   string some1 = "someone";
   return string.Format(template, some1, "inplacesomethingelse");
 }

 public string FormatExample2() {
   string some2 = "someoneelse";
   string thing2 = "somethingelse";
   return string.Format(template, some2, thing2);
 }
}

Việc sử dụng toàn cầu không thực sự ổn và bên cạnh đó - nó cũng không hoạt động với toàn cầu

 static class Example2_Format {
 //must have declaration in same scope
 static string some = "";
 static string thing = "";
 static string template = $"{some} - {thing}";

//This returns " - " and not "someone - something" as you would maybe 
//expect
 public static string FormatExample1() {
   some = "someone";
   thing = "something";
   return template;
 }

//This returns " - " and not "someoneelse- somethingelse" as you would 
//maybe expect
 public static string FormatExample2() {
   some = "someoneelse";
   thing = "somethingelse";
   return template;
 }
}

Câu trả lời này rất quan trọng vì nó chỉ ra rằng phép nội suy xảy ra khi bạn "gọi" chuỗi $, chứ không phải khi bạn khai báo nó.
dx_over_dt

1
Bạn đúng về mô hình chống khai báo các biến nội suy của bạn ở phạm vi lớp, tuy nhiên nếu các biến đó đã thuộc về các thuộc tính lớp, thì mẫu này hoạt động tốt.
dx_over_dt

@dx_over_dt Bạn sai rồi. Các chuỗi nội suy được đánh giá tại thời điểm chúng được khai báo. Đó là lý do tại sao mã mẫu không có ý nghĩa. Nó cũng sẽ không biên dịch.
Nine tweet

@Nine BlackBerry Bạn đúng cả về các chuỗi nội suy được đánh giá tại thời điểm chúng được khai báo và về Ví dụ_ $ Format không biên dịch và về mã mẫu không có ý nghĩa :) Tôi đã sửa mẫu để giải thích rõ hơn.
Tom

5

Tôi không biết làm thế nào nó hoạt động, nhưng bạn cũng có thể sử dụng nó để tab các giá trị của bạn!

Thí dụ :

Console.WriteLine($"I can tab like {"this !", 5}.");

Tất nhiên, bạn có thể thay thế "này!" với bất kỳ biến hoặc bất cứ điều gì có ý nghĩa, giống như bạn cũng có thể thay đổi tab.


vâng, bạn cũng có thể định dạng chuỗi msdn.microsoft.com/en-us/l
Library / dn961160.aspx

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.