developer tip

인덱스 자리 표시 자 대신 명명 된 입력 매개 변수를 허용 할 수있는 "String.Format"이 있습니까?

optionbox 2020. 9. 13. 10:23
반응형

인덱스 자리 표시 자 대신 명명 된 입력 매개 변수를 허용 할 수있는 "String.Format"이 있습니까? [복제]


이것이 내가 아는 것

str = String.Format("Her name is {0} and she's {1} years old", "Lisa", "10");

하지만 나는

str = String("Her name is @name and she's @age years old");
str.addParameter(@name, "Lisa");
str.addParameter(@age, 10);

C # 6에서는 문자열 보간을 사용할 수 있습니다 .

string name = "Lisa";
int age = 20;
string str = $"Her name is {name} and she's {age} years old";

으로 더그 클러가 에 언급 된 그의 주석 , 문자열 보간도 지원 형식 문자열을 . 콜론 뒤에 지정하여 형식을 변경할 수 있습니다. 다음 예제는 쉼표와 소수점 2 자리가있는 숫자를 출력합니다.

var str = $"Your account balance is {balance:N2}"

바스가 에 언급 된 그의 대답 , 문자열 보간 템플릿 문자열을 지원하지 않습니다. 사실, 그것에 대한 지원이 내장되어 있지 않습니다. 다행히도 훌륭한 도서관에 존재합니다.


예를 들어 SmartFormat.NET 은 명명 된 자리 표시자를 지원합니다.

Smart.Format("{Name} from {Address.City}, {Address.State}", user)

// The user object should at least be like that 

public class User
{
    public string Name { get; set; }
    public Address Address { get; set; }
}

public class Address
{
    public string City { get; set; }
    public string State { get; set; }
}

NuGet에서 사용할 수 있습니다 .


콧수염 도 훌륭한 솔루션입니다. Bas 그의 대답 에서 그 장점을 잘 설명했습니다.


템플릿 매개 변수를 대체하는 데 사용하는 데이터가 포함 된 지역 변수를 할당해도 괜찮다면 C # 6.0 문자열 보간 기능을 사용할 수 있습니다 .

기본 원칙은 입력 데이터를 기반으로 상당히 고급 문자열 대체 논리를 수행 할 수 있다는 것입니다.

간단한 예 :

string name = "John";
string message = $"Hello, my name is {name}."

복잡한 예 :

List<string> strings = ...
string summary = $"There are {strings.Count} strings. " 
  + $"The average length is {strings.Select(s => s.Length).Average()}"

단점 :

  • 동적 템플릿에 대한 지원 없음 (예 : 리소스 파일에서)

(주요) 장점 :

  • 템플릿 교체 시 컴파일 시간 검사시행 합니다.

거의 동일한 구문을 가진 멋진 오픈 소스 솔루션은 Mustache 입니다. 내가 찾을 수있는 두 가지 사용 가능한 C # 구현 -mustache -sharpNustache .

나는 함께 일했고 mustache-sharp그것이 문자열 보간과 같은 힘을 가지고 있지 않지만 가깝다는 것을 발견했습니다. 예를 들어 다음을 수행 할 수 있습니다 (github 페이지에서 도난 당함).

Hello, {{Customer.Name}}
{{#newline}}
{{#newline}}
{{#with Order}}
{{#if LineItems}}
Here is a summary of your previous order:
{{#newline}}
{{#newline}}
{{#each LineItems}}
    {{ProductName}}: {{UnitPrice:C}} x {{Quantity}}
    {{#newline}}
{{/each}}
{{#newline}}
Your total was {{Total:C}}.
{{#else}}
You do not have any recent purchases.
{{/if}}
{{/with}}

프로젝트에서 사용할 수있는 C # 6이없는 경우 Linq의 .Aggregate ()를 사용할 수 있습니다.

    var str = "Her name is @name and she's @age years old";

    var parameters = new Dictionary<string, object>();
    parameters.Add("@name", "Lisa");
    parameters.Add("@age", 10);

    str = parameters.Aggregate(str, (current, parameter)=> current.Replace(parameter.Key, parameter.Value.ToString()));

질문의 특정 구문과 일치하는 것을 원한다면 Aggregate를 기반으로 매우 간단한 클래스를 구성 할 수 있습니다.

public class StringFormatter{

    public string Str {get;set;}

    public Dictionary<string, object> Parameters {get;set;}

    public StringFormatter(string p_str){
        Str = p_str;
        Parameters = new Dictionary<string, object>();
    }

    public void Add(string key, object val){
        Parameters.Add(key, val);
    }

    public override string ToString(){
        return Parameters.Aggregate(Str, (current, parameter)=> current.Replace(parameter.Key, parameter.Value.ToString()));
    }

}

다음과 같이 사용 가능 :

var str = new StringFormatter("Her name is @name and she's @age years old");
str.Add("@name", "Lisa");
str.Add("@age", 10);

Console.WriteLine(str);

Note that this is clean-looking code that's geared to being easy-to-understand over performance.


With C# 6 you can use String Interpolation to directly add variables into a string.

For example:

string name = "List";
int age = 10;

var str = $"Her name is {name} and she's {age} years old";

Note, the use of the dollar sign ($) before the string format.


So why not just Replace?

string str = "Her name is @name and she's @age years old";
str = str.Replace("@name", "Lisa");
str = str.Replace("@age", "10");

There is no built in way to do this, but you can write a class that will do it for you.
Something like this can get you started:

public class ParameterizedString
{
    private string _BaseString;
    private Dictionary<string, string> _Parameters;

    public ParameterizedString(string baseString)
    {
        _BaseString = baseString;
        _Parameters = new Dictionary<string, string>();
    }

    public bool AddParameter(string name, string value)
    {
        if(_Parameters.ContainsKey(name))
        {
            return false;
        }
        _Parameters.Add(name, value);
        return true;
    }

    public override string ToString()
    {
        var sb = new StringBuilder(_BaseString);
        foreach (var key in _Parameters.Keys)
        {
            sb.Replace(key, _Parameters[key]);
        }
        return sb.ToString();
    }
}

Note that this example does not force any parameter name convention. This means that you should be very careful picking your parameters names otherwise you might end up replacing parts of the string you didn't intend to.


string interpolation is a good solution however it requires C#6.

In such case I am using StringBuilder

var sb = new StringBuilder();

sb.AppendFormat("Her name is {0} ", "Lisa");
sb.AppendFormat("and she's {0} years old", "10");
// You can add more lines

string result = sb.ToString();

You can also use expressions with C#6's string interpolation:

string name = "Lisa";
int age = 20;
string str = $"Her name is {name} and she's {age} year{(age == 1 ? "" : "s")} old";

    string name = "Lisa";
    int age = 20;
    string str = $"Her name is {name} and she's {age} years old";

This is called an Interpolated String, which is a basically a template string that contains expressions inside of it.

참고URL : https://stackoverflow.com/questions/36759694/is-there-a-string-format-that-can-accept-named-input-parameters-instead-of-ind

반응형