Названное строковое форматирование в C#

Я помещаю превосходный ответ JLBorges на аналогичный вопрос дословно из cplusplus.com, так как это наиболее краткое объяснение, которое я прочитал по этому вопросу.

] В шаблоне, который мы пишем, есть два типа имен, которые можно использовать - зависимые имена и не зависимые имена. Зависимое имя - это имя, которое зависит от параметра шаблона; неизменяемое имя имеет то же значение, независимо от параметров шаблона.

Например:

template< typename T > void foo( T& x, std::string str, int count )
{
    // these names are looked up during the second phase
    // when foo is instantiated and the type T is known
    x.size(); // dependant name (non-type)
    T::instance_count ; // dependant name (non-type)
    typename T::iterator i ; // dependant name (type)

    // during the first phase, 
    // T::instance_count is treated as a non-type (this is the default)
    // the typename keyword specifies that T::iterator is to be treated as a type.

    // these names are looked up during the first phase
    std::string::size_type s ; // non-dependant name (type)
    std::string::npos ; // non-dependant name (non-type)
    str.empty() ; // non-dependant name (non-type)
    count ; // non-dependant name (non-type)
}

То, что зависит от зависимого имени, может быть чем-то другим для каждого конкретного экземпляра шаблона. Как следствие, шаблоны C ++ подвержены «двухфазному поиску имен». Когда шаблон сначала анализируется (до того, как выполняется какое-либо создание), компилятор просматривает не зависящие имена. Когда происходит конкретное создание шаблона, параметры шаблона известны к тому времени, и компилятор ищет зависимые имена.

На первом этапе анализатор должен знать, является ли зависимое имя именем типа или имени не-типа. По умолчанию зависимым именем считается имя не-типа.

Использовать ключевое слово typename только в объявлениях шаблонов и определениях, приведенных ниже.

blockquote>

у вас есть квалифицированное имя, которое относится к типу и зависит от параметра шаблона.

155
задан Robert Harvey 16 August 2016 в 17:59
поделиться

8 ответов

Нет никакого встроенного метода для обработки этого.

Вот один метод

string myString = "{foo} is {bar} and {yadi} is {yada}".Inject(o);

, Вот другой

Status.Text = "{UserName} last logged in at {LastLoginDate}".FormatWith(user);

, треть А улучшила метод частично на основе двух выше от Phil Haack

128
ответ дан Jeff Atwood 23 November 2019 в 21:55
поделиться
string language = "Python";
int numquotes = 2;
string output = language + " has "+ numquotes + " language types.";

Редактирование: То, что я должен был сказать, было, "Нет, я не верю тому, что Вы хотите сделать, поддерживается C#. Это настолько близко, как Вы собираетесь добраться".

-6
ответ дан Kevin 23 November 2019 в 21:55
поделиться

Я сомневаюсь, что это будет возможно. Первая вещь, которая приходит на ум, состоит в том, как Вы собираетесь получить доступ к именам локальной переменной?

мог бы быть некоторый умный способ использовать LINQ и Лямбда-выражения, чтобы сделать это как бы то ни было.

1
ответ дан leppie 23 November 2019 в 21:55
поделиться

Я думаю самое близкое, которое Вы получите, индексируемый формат:

String.Format("{0} has {1} quote types.", "C#", "1");

существует также Строка. Замена (), если Вы готовы сделать это на нескольких шагах и взять его на вере, что Вы не найдете свои 'переменные' больше нигде в строке:

string MyString = "{language} has {n} quote types.";
MyString = MyString.Replace("{language}", "C#").Replace("{n}", "1");

Расширение этого для использования Списка:

List<KeyValuePair<string, string>> replacements = GetFormatDictionary();  
foreach (KeyValuePair<string, string> item in replacements)
{
    MyString = MyString.Replace(item.Key, item.Value);
}

Вы могли сделать это с Dictionary< строка, строка> также путем итерации это-.Keys наборы, но при помощи List< KeyValuePair< строка, строка>> мы можем использовать в своих интересах.ForEach Списка () метод и уплотнить его назад к остроте:

replacements.ForEach(delegate(KeyValuePair<string,string>) item) { MyString = MyString.Replace(item.Key, item.Value);});

лямбда А была бы еще более простой, но я нахожусь все еще на.Net 2.0. Также обратите внимание, что.Replace () производительность не является звездной, когда используется многократно, так как строки в.Net неизменны. Кроме того, это требует MyString, переменная определяется таким способом, которым это доступно для делегата, таким образом, это еще не прекрасно.

4
ответ дан 7 revs 23 November 2019 в 21:55
поделиться

См. https://stackoverflow.com/questions/271398? page=2#358259

Со связанным - к расширению можно записать это:

var str = "{foo} {bar} {baz}".Format(foo=>"foo", bar=>2, baz=>new object());

и Вы доберетесь "foo 2 System.Object".

6
ответ дан Community 23 November 2019 в 21:55
поделиться

Сама платформа не позволяет делать это, но можно смотреть на это сообщение Scott Hanselman. Использование в качестве примера:

Person p = new Person();  
string foo = p.ToString("{Money:C} {LastName}, {ScottName} {BirthDate}");  
Assert.AreEqual("$3.43 Hanselman, {ScottName} 1/22/1974 12:00:00 AM", foo); 

Этот код James Newton-King подобен и работает с подсвойствами и индексами,

string foo = "Top result for {Name} was {Results[0].Name}".FormatWith(student));

, код James полагается Система. Сеть. UI.DataBinder для парсинга строки и требует Системы ссылки. Сеть, которую некоторым людям не нравится делать в невеб-приложениях.

РЕДАКТИРОВАНИЕ: О, и они работают приятно с анонимными типами, если у Вас нет объекта со свойствами готовым к нему:

string name = ...;
DateTime date = ...;
string foo = "{Name} - {Birthday}".FormatWith(new { Name = name, Birthday = date });
9
ответ дан Lucas 23 November 2019 в 21:55
поделиться

Кажется, нет способа сделать это из поля. Хотя, выглядит выполнимым реализовать Ваше собственное IFormatProvider , который связывается с IDictionary для значений.

var Stuff = new Dictionary<string, object> {
   { "language", "Python" },
   { "#", 2 }
};
var Formatter = new DictionaryFormatProvider();

// Interpret {0:x} where {0}=IDictionary and "x" is hash key
Console.WriteLine string.Format(Formatter, "{0:language} has {0:#} quote types", Stuff);

Выводы:

Python has 2 quote types

протест состоит в том, что Вы не можете смешаться FormatProviders, таким образом, необычное текстовое форматирование не может использоваться одновременно.

14
ответ дан spoulson 23 November 2019 в 21:55
поделиться

У меня есть реализация, которую я просто разместил в своем блоге здесь: http://haacked.com/archive/2009/01/04/fun-with-named-formats-string-parsing-and-edge-cases.aspx

Это решает некоторые проблемы, которые эти другие реализации имеют с выходом фигурной скобки. Сообщение имеет детали. Это делает DataBinder. Вещь оценки также, но все еще очень быстро.

45
ответ дан Haacked 23 November 2019 в 21:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: