Mengapa menggunakan metode generik dengan batasan tipe dan bukan tipe itu sendiri?

14

Dalam pertanyaan StackExchange yang berbeda, saya perhatikan seseorang menggunakan prototipe ini:

void DoSomething<T>(T arg) where T: SomeSpecificReferenceType
{
    //Code....
}

Mengingat hanya ada satu jenis kendala ( SomeSpecificReferenceType), apa perbedaan dan keuntungan menulisnya seperti itu, bukan hanya:

void DoSomething(SomeSpecificReferenceType arg)
{
    //Code....
}

Dalam kedua kasus, argakan dikenakan pemeriksaan jenis waktu kompilasi. Dalam kedua kasus, tubuh metode dapat dengan aman mengandalkan pengetahuan yang arg(atau merupakan keturunan) jenis tertentu yang dikenal pada waktu kompilasi.

Apakah ini kasus pengembang yang terlalu bersemangat belajar tentang obat generik sebelum belajar tentang warisan biasa? Atau adakah alasan yang sah mengapa tanda tangan metode ditulis seperti ini?

John Wu
sumber
Saya hampir tidak tahu C # jadi ini hanya dugaan, tetapi bukankah ini memungkinkan pengiriman statis yang lebih efisien daripada pengiriman dinamis?
Anton Barkovsky

Jawaban:

13

Apakah ini kasus pengembang yang terlalu bersemangat belajar tentang obat generik sebelum belajar tentang warisan biasa?

Ya, mungkin memang begitu.

Atau adakah alasan yang sah mengapa tanda tangan metode ditulis seperti ini?

Mungkin . Secara umum, akan lebih masuk akal jika ada nilai balik yang terlibat T, atau parameter lain yang digunakan T.

Tapi, mungkin saja internal menggunakan kode T(mungkin sebagai argumen untuk serializer?) Dan perlu menggunakan secara khusus Tdan bukan kelas kendala. Anda kadang-kadang akan melihat bahwa ketika kendala adalah antarmuka yang dipasangkan dengan newkendala dan keberanian dari metode menciptakan Tuntuk beberapa alasan.

Jadi walaupun jarang melihat versi kendala yang dibutuhkan, ada kalanya itu. Dan selalu mungkin bahwa metode dulu membutuhkannya, tetapi sekarang tidak dan pengembang membiarkannya untuk tidak memperkenalkan perubahan yang melanggar.

Telastyn
sumber
1

Saya pikir saya ingat diri saya mengetik jawaban yang berisi ini.

Pada saat itu alasannya seperti ini:
(Kode mungkin berbeda. Hanya untuk mengilustrasikan salah satu alasan yang mungkin mengapa ada batasan pada parameter tipe dalam metode generik.)

class SomeSingleton
{
    static Dictionary<Type, List<object>> staticTypeSpecificList;
    public void AddObjectToList<T>(T t) where T : SomeCommonThing
    {
        Type tt = t.GetType();
        List<object> list;
        if (!staticTypeSpecificList.TryGet(tt, out list))
        {
            list = new List<object>();
            staticTypeSpecificList.Add(tt, list);
        }
        list.Add(t);
    }
}

Pada dasarnya, kode masuk ke manipulasi jenis coding secara manual itu sendiri. Mungkin juga dicampur dengan beberapa hal refleksi.

Misalnya, dengan menggunakan Method<T>(T arg) where T : ..., seseorang dapat mengganti arg.GetType()dengan typeof(T). Padahal, saya tidak tahu apakah pilihan itu baik atau buruk.

Saya kira ini hanyalah contoh dari penulis (mungkin saya, atau orang lain) yang tidak dengan hati-hati memikirkan semua kemungkinan pengkodean, pada saat yang sama terlalu fokus pada pertanyaan / masalah yang berbeda.

rwong
sumber
"seseorang dapat mengganti arg.GetType () dengan typeof (T)". Ini berguna ketika arg secara valid dapat menjadi null, misalnya dalam beberapa kasus serialisasi.
walpen