9

クラスレベルでの宣言とメソッドレベルでの同じ文字(異なる意味) について話しているこの興味深い質問を見ました。TT

だから私はテストをしました。

  static void Main(string[] args)
        {
            var c = new MyClass<int>(); //T is int
            c.MyField = 1;
            c.MyProp = 1;
            c.MyMethod("2");
        }


        public class MyClass<T>
        {
            public T MyField;
            public T MyProp { get; set; }
            public void MyMethod<T>(T k)
            {
            }
        }

エリックが言ったように、コンパイラは警告します。

しかしねえ、型安全性はどうなったのですか?メソッドレベルには型安全性があると思いますが、すでに宣言されているクラスのグローバルコンテキストについてはどうでしょうか。T

つまり、誰かが私に尋ねたとしたら、警告ではなくエラーがあるはずだと思います。

なぜコンパイラはそれを許可するのですか?(私は合理的な答えを聞きたいです

4

2 に答える 2

3

興味深い質問です。ここではタイプ セーフが維持されます。動作は、グローバル変数とローカル変数に似ています。MyMethodでは、型Tは明確です。次のようにMyClassの新しいインスタンスを作成して返すこともできます。

public class MyClass<T>
{
    public T MyField;
    public T MyProp { get; set; }
    public MyClass<T> MyMethod<T>(T k)
    {
        return new MyClass<T>();
    }
}

プログラム:

static void Main()
{
    var c = new MyClass<int>(); //T is int
    c.MyField = 1;
    c.MyProp = 1;

    var myClass = c.MyMethod("2");
    myClass.MyField = "2";
    myClass.MyField = "4";
}

タイプ セーフが保持されているため、コンパイル エラーは発生しません。プログラムをコンパイルできます。あいまいさはありません。

Tは対応するクラス レベルをオーバーライドし、そのグローバルTを取得する簡単な方法がMyMethodにないため、警告が表示されるはずです。また、可読性を妨げます。

MSDN は、ジェネリック メソッド (C# プログラミング ガイド)の柔軟性と優れた実践について次のように述べています。

含まれているクラスと同じ型パラメーターを取るジェネリック メソッドを定義すると、コンパイラーは警告 CS0693 を生成します。これは、メソッド スコープ内で、内側の T に指定された引数が外側の T に指定された引数を隠すためです。クラスがインスタンス化されたときに提供されたもの以外の型引数を使用してジェネリック クラス メソッドを呼び出す場合は、メソッドの型パラメーターに別の識別子を提供することを検討してください。

于 2013-02-26T09:29:46.857 に答える
2

これはタイプ セーフの問題ではありません。これは読みやすさの問題にすぎません。そのため、単なる警告です。(また、T は外側の T を隠します。)

MyMethod() を次のように変更した場合:

public void MyMethod<T>(T k)
{
    Console.WriteLine(typeof(T).FullName);
}

サンプル コードの System.String が出力され、正しい型が取得されていることが証明されます。

于 2013-02-26T09:29:53.040 に答える