6

書式文字列の全文が静的でコンパイル時に既知である場合、書式文字列パラメータの欠落はコンパイル時のエラーまたは少なくとも警告ではないでしょうか?

ReSharper はこれをキャッチしますが、下線付きの波線にすぎません。これにより、一般的なコンパイル時エラーが発生するという印象を受けました。

string x = string.Format("soeuotnh {0}");

FxCop などを介してコードを実行することなく、この種のエラーで警告をトリガーする方法はありますか? C/C++ コンパイラでさえ、そのような露骨に明らかなバグに対して警告/エラーを引き起こします (ただし、通常はタイプ セーフをチェックしません)。

4

7 に答える 7

2

It could be a warning, but should it be? Well, that's up to the compiler team I suppose, it's not like String.Format is a part of the C# language.

This isn't C; you're not invoking undefined behavior or anything, the method can simply deal with the missing parameter and the assumption is (I assume...) that you will catch it pretty quickly when it throws an exception. There's nothing "dangerous" about it, it's just a logic error.

于 2012-04-17T16:36:47.843 に答える
2

この状態を自動的に検出するには、あなたが言及した方法以外に方法はないと思います。これが発生する理由については、Format メソッドが(String, params Object[])オーバーロードと一致しており、パラメーターはドキュメントで次のように定義されています

public static string Format(
    string format,
    params Object[] args
)

format 型: System.String
複合フォーマット文字列 (「備考」を参照)。

args 型: System.Object[] 書式設定する0個以上のオブジェクトを含むオブジェクト配列。

は可変数の引数 (ゼロ引数を含む) を定義するため、コンパイル時に例外がスローされparamsません。

編集:

コンパイラが選択する有効なオーバーロードがあるため、コンパイル時エラーは発生しません。したがって、これがコンパイラの問題になることはなくなります。最善の策は、コード品質ツールである Resharper を使用してこの状態を検出することです。

于 2012-04-17T16:37:13.513 に答える
0

一部の C コンパイラは、フォーマット文字列を解析します。これは、パラメータと一致しないフォーマット文字列があると、重大なクラッシュ バグ、またはさらに悪いことにセキュリティ バグが発生する可能性があるためです。ただし、C# では、呼び出しサイトで例外が発生するだけなので、重要ではありません。

コンパイラはそれを行うことができますが、それにはコードが特殊なケースとして認識する必要がありstring.Format、(さらに悪いことに) C# コンパイラでフォーマット文字列パーサーを作成する必要があります。すべては、実行されるたびにクラッシュするコードについて警告できるようにするためです。

これに関する大きな問題は、多くの人がすべての警告をオンにして警告をエラーとしてコンパイルすることです。つまり、この警告を追加するとビルドが壊れることになります。実行されたことのないコードの隅に不適切なフォーマット文字列があると、突然製品をビルドできなくなります。これらの人々は文句を言うでしょう。

于 2012-04-17T16:48:55.823 に答える
0

すでに述べたように、これはコンパイラが行うことでも、気にする必要もないことです。

次のようなことを行うときにコンパイラがどのように動作すると予想しますか。

string format = "{0}";
List<string> parms = new List<string> { "Hello" };

if (DateTime.Now.Second % 2 == 0)
{
    format += " {1}";
    parms.Add("World");
}

Console.WriteLine(format, parms.ToArray());
于 2012-04-17T16:50:43.357 に答える
0

Resharperはこの場合、「フォーマット文字列に存在しない引数」という警告を表示します。

于 2012-04-17T16:55:47.733 に答える
-1

私は、Microsoft Connect でこの機能の検討を依頼しました。

  • 「あまりホットなコードパスではない場合、人々は自分のコードをコンパイルして実行時に失敗することを好むだろう」という答えはばかげており、解釈されない言語、特に明示的に定義された強く型付けされた言語ではありません。 C# としてのタイプ セーフの重要性。
  • コンパイラがコンパイル時にフォーマット文字列とパラメータ配列を物理的に推測できないという答えも正しくありません。はい、コンパイル時にコンパイラがどちらか一方 (または両方) を推測できない場合があり、それらについては何もできませんが、他の多くの場合、完全な情報を自由に使用できます。
  • 仕様がこの種の動作に対して警告をスローすることについて言及していないという理由だけで、これは完全にコンパイラの仕事ではないという答えには、仕様がコンパイラが実装する必要がある最小のものであり、コンパイラが無料であるという事実が欠けています(そして仕様と矛盾しない限り、それ以上のことを行う必要があります。
  • C コンパイラがこれを行わないという回答も明らかに間違っています。それ以外の例を投稿しました。
  • 私が投稿したコードサンプルが実行時に例外をスローしないという回答は、明らかに間違っています (ただし、ほとんどはその後編集されています)。

結局のところ、それは「できる、できない、そうすべきかもしれない」という状況です。警告をより積極的にするためにコンパイラ(サードパーティのソフトウェアではなく)に設定できるものがないこと、またはコードを変更して例外をスローさせる方法がないことを確認しようとしていました(たとえば、すべてを const として宣言します) が、(これまでのところ) それは不可能であることが判明しています。私が MS Connect で公開した問題に対する Visual Studio チームの反応に関係なく、コンパイラはコンパイル時に非常に多くの文字列形式の例外を確かにキャッチできるという事実は残っています。 VS チームは、実装する価値があるかどうかを判断します。

于 2012-04-18T18:16:46.760 に答える
-1

メソッドの「フォーマット」パラメーターは定数ではありません。一定でないものはすべて、コンパイル時にチェックできません。

さまざまな方法で実行時に構成でき、ユーザー入力も可能です... (恐ろしい!)

そのため、コンパイル時エラーではありません。

編集: OK、それが定数式の場合分析され、警告が生成される可能性があります。しかし、少し当てはまる別の質問に対する Eric Lipert の回答は次のとおりです。

これが、String.Format (およびおそらく他の文字列形式関数) の特殊なケースのシナリオを費やす価値がある本当の利点であるかどうかは、難しい問題です。

于 2012-04-17T16:45:13.953 に答える