28

私は文字列を持っています

string str ="Enter {0} patient name";

string.format を使用してフォーマットしています。

String.Format(str, "Hello");

ここで、患者もいくつかの構成から取得したい場合は、 str を のようなものに変更する必要があります "Enter {0} {1} name"。したがって、{1} を 2 番目の値に置き換えます。問題は、{1} の代わりに{pat}. しかし、使用しようとすると、エラーがスローされます。別の形式が必要な理由は、このように変更する必要があるファイルがたくさんあるためです ({0}、{1} などを含む可能性があります)。そのため、実行時に置き換えることができるカスタム プレースホルダーが必要です。

4

8 に答える 8

54

James Newton-KingによるFormatWith 2.0をチェックしてみてください。プロパティ名を次のようなフォーマット トークンとして使用できます。

var user = new User()
{
    Name = "Olle Wobbla",
    Age = 25
};

Console.WriteLine("Your name is {Name} and your age is {Age}".FormatWith(user));

匿名型でも使用できます。

更新: Scott Hanselmanによる同様のソリューションもありますが、 の代わりに拡張メソッドのセットとして実装されています。ObjectString

UPDATE 2012 : Calrius Consulting のNETFx String.FormatWith 拡張メソッドNuGet パッケージは、NuGet.orgで入手できます。

UPDATE 2014 : StringFormat.NETlittlebit の StringFormatもあります

于 2009-07-09T07:28:20.547 に答える
21

RegexMatchEvaluator良いオプションのようです:

static readonly Regex re = new Regex(@"\{([^\}]+)\}", RegexOptions.Compiled);
static void Main()
{
    string input = "this {foo} is now {bar}.";
    StringDictionary fields = new StringDictionary();
    fields.Add("foo", "code");
    fields.Add("bar", "working");

    string output = re.Replace(input, delegate (Match match) {
        return fields[match.Groups[1].Value];
    });
    Console.WriteLine(output); // "this code is now working."
}
于 2009-07-09T07:22:58.327 に答える
3
object[] myInts = new int[] {8,9}; 

しかし、あなたは逃げることができます:

object[] myInts = new string[] { "8", "9" }; 
string bar = string.Format("{0} {1}", myInts); 
于 2012-02-23T14:26:36.877 に答える
3

上記のすべての回答を見ましたが、質問を正しく理解できませんでした:)

次のコードが要件を満たさない特定の理由はありますか?

string myFirstStr = GetMyFirstStrFromSomewhere();
string mySecondStr = GetMySecondStrFromSomewhere();

string result = "Enter " + myFirstStr + " " + mySecondStr + " name";
于 2009-07-09T07:54:58.013 に答える
2

これが私がここで見つけた別のバージョンです:http://www.reddit.com/r/programming/comments/bodml/beef_up_params_in_c_5_to_solve_lambda_abuse/c0nrsf1

これに対する解決策にはリフレクションが含まれますが、これは理想的とは言えませんが、他の主要なパフォーマンスの問題のいくつかが解決された彼のコードを次に示します。(エラーチェックはありません。必要に応じて追加してください。):

1)DataBinderオーバーヘッドなしで、直接ランタイムリフレクションを使用します

2)正規表現を使用せず、シングルパスの解析と状態を使用します。

3)文字列を中間文字列に変換してから、再度最終形式に変換しません。

4)文字列をあちこちで更新して新しい文字列に連結するのではなく、単一のStringBuilderで割り当てて連結します。

5)n個の置換操作のデリゲートを呼び出すスタックオーバーヘッドを削除します。

6)一般に、比較的直線的にスケーリングするシングルパススルーです(各プロップルックアップとネストされたプロップルックアップにはまだいくらかのコストがかかりますが、それだけです)。

public static string FormatWith(this string format, object source)
{
    StringBuilder sbResult = new StringBuilder(format.Length);
    StringBuilder sbCurrentTerm = new StringBuilder();
    char[] formatChars = format.ToCharArray();
    bool inTerm = false;
    object currentPropValue = source;

    for (int i = 0; i < format.Length; i++)
    {
        if (formatChars[i] == '{')
            inTerm = true;
        else if (formatChars[i] == '}')
        {
            PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
            sbResult.Append((string)(pi.PropertyType.GetMethod("ToString", new Type[]{}).Invoke(pi.GetValue(currentPropValue, null), null)));
            sbCurrentTerm.Clear();
            inTerm = false;
            currentPropValue = source;
        }
        else if (inTerm)
        {
            if (formatChars[i] == '.')
            {
                PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
                currentPropValue = pi.GetValue(source, null);
                sbCurrentTerm.Clear();
            }
            else
                sbCurrentTerm.Append(formatChars[i]);
        }
        else
            sbResult.Append(formatChars[i]);
    }
    return sbResult.ToString();
} 
于 2013-02-18T22:23:48.873 に答える
1

次のように、カスタム フィールドには Replace を使用し、残りのフィールドには Format を使用することをお勧めします。

string str = "Enter {0} {pat} name";
String.Format(str.Replace("{pat}", "Patient"), "Hello");
于 2009-07-09T07:30:13.630 に答える