Meneruskan hanya tipe sebagai parameter di C #

130

Secara hipotetis, akan berguna bagi saya untuk melakukan ini:

foo.GetColumnValues(dm.mainColumn, int)
foo.GetColumnValues(dm.mainColumn, string)

di mana metode GetColumns akan memanggil metode yang berbeda di dalam tergantung pada jenis yang diteruskan.

Ya, saya bisa melakukannya sebagai bendera boolean atau serupa, saya hanya bertanya-tanya apakah mungkin ada cara untuk melewati ini, dan kemudian bertanya:

typeof (arg [1]) atau serupa ...

Saya juga bisa mengganti metode, menggunakan obat generik, dll - Saya tahu ada berbagai cara untuk melakukan ini, saya hanya ingin tahu apakah ini mungkin.

Mark Mayo
sumber
Pikiranku tepatnya, tergantung dari apa sebenarnya foo itu. foo.GetColumnValues<int>(dm.mainColumn)mungkin cara untuk pergi.
Produksi Utama
1
Seperti yang saya katakan, saya menyadari ada cara lain untuk melakukan ini (boolean flag, generics, overriding the method) Saya hanya bertanya-tanya apakah itu mungkin sebagai parameter.
Mark Mayo
@MarkMayo: Saya tidak mengerti pertanyaan jika Anda "tahu bahwa Anda juga dapat menimpa metode ini, menggunakan obat generik, dll dan Anda tahu bahwa ada berbagai cara untuk melakukan ini, Anda hanya ingin tahu apakah ini mungkin" . Jadi Anda tahu semua ini tetapi Anda penasaran apakah itu mungkin ??
Tim Schmelter
@TimSchmelter - dalam bentuk yang saya jelaskan. yaitu meneruskannya sebagai parameter ke-2. Ternyata, Reed agak mengatakan apa yang saya cari - di mana Anda menggunakan (..., Jenis tipe). Itulah yang saya cari.
Mark Mayo
1
Pertanyaan bagus, upvoted, saya melihat MS menggunakan Type sebagai parameter untuk operator built-in di VB.NET misalnya trycast, dan sering berharap saya bisa melakukannya sendiri di C # / VB - dengan cara yang Anda gambarkan.
Chalky

Jawaban:

213

Ada dua pendekatan umum. Pertama, Anda bisa lewatSystem.Type

object GetColumnValue(string columnName, Type type)
{
    // Here, you can check specific types, as needed:

    if (type == typeof(int)) { // ...

Ini akan disebut seperti: int val = (int)GetColumnValue(columnName, typeof(int));

Pilihan lainnya adalah menggunakan obat generik:

T GetColumnValue<T>(string columnName)
{
    // If you need the type, you can use typeof(T)...

Ini memiliki keuntungan untuk menghindari tinju dan memberikan beberapa jenis keamanan, dan akan disebut seperti: int val = GetColumnValue<int>(columnName);

Reed Copsey
sumber
1
Anda juga dapat melakukan metode ekstensi, public T GetColumnValue <T> (string ini nama kolom) {...} maka Anda dapat mengatakan foo.GetColumnValues ​​<string> (dm.mainColumn)
Joshua G
Tetapi bagaimana Anda mendefinisikan metode yang memiliki beberapa argumen dan salah satunya harus generik? Karena generik didefinisikan sebelum daftar argumen metode, bagaimana Anda tahu mana yang harus menjadi generik?
BadmintonCat
5
@BadmintonCat T Foo<T,U>(string arg1, U arg2)atau sejenisnya
Reed Copsey
Saat menggunakan pendekatan pertama, apakah ada cara untuk menetapkan nilai default untuk diketik? (misalnya, sesuatu seperti object GetColumnValue(string columnName, Type type = object)? Tampaknya tidak berhasil bagi saya, tetapi akan berguna untuk mengetahuinya.
Dave Cole
22

foo.GetColumnValues(dm.mainColumn, typeof(string))

Alternatifnya, Anda bisa menggunakan metode umum:

public void GetColumnValues<T>(object mainColumn)
{
    GetColumnValues(mainColumn, typeof(T));
}

dan Anda kemudian dapat menggunakannya seperti:

foo.GetColumnValues<string>(dm.mainColumn);
Peter Ritchie
sumber
13

Anda dapat mengirimkan tipe sebagai argumen, tetapi untuk melakukannya Anda harus menggunakan typeof:

foo.GetColumnValues(dm.mainColumn, typeof(int))

Metode tersebut perlu menerima parameter dengan tipe Type.


di mana metode GetColumns akan memanggil metode yang berbeda di dalam tergantung pada jenis yang diteruskan.

Jika Anda menginginkan perilaku ini maka Anda tidak boleh meneruskan tipe sebagai argumen melainkan menggunakan parameter tipe.

foo.GetColumnValues<int>(dm.mainColumn)
Mark Byers
sumber
8
foo.GetColumnValues(dm.mainColumn, typeof(int));
foo.GetColumnValues(dm.mainColumn, typeof(string));

Atau menggunakan obat generik:

foo.GetColumnValues<int>(dm.mainColumn);
foo.GetColumnValues<string>(dm.mainColumn);
Danny Varod
sumber
3
Saya tidak memberikan Anda, tapi itu mungkin karena Anda menunjukkan bagaimana itu akan dipanggil dan tidak menentukan definisi fungsinya
JConstantine
3
Aku benci kalau orang butuh makan sendok. Jawabannya + bacaan singkat tentang MSDN sudah cukup. Saya menduga bahwa pemilih yang down-voters adalah penjawab yang bersaing dengan reputasi yang sangat kecil.
Danny Varod
1

Anda bisa melakukan ini, cukup bungkus typeof()

foo.GetColumnValues(typeof(int))

public void GetColumnValues(Type type)
{
    //logic
}
Kevin DiTraglia
sumber
0

Anda dapat menggunakan argumen tipe Type - iow, pass typeof (int). Anda juga dapat menggunakan obat generik untuk pendekatan (mungkin lebih efisien).

500 Internal Server Error
sumber
0

Gunakan tipe generik!

  class DataExtraction<T>
{
    DateRangeReport dateRange;
    List<Predicate> predicates;
    List<string> cids;

    public DataExtraction( DateRangeReport dateRange,
                           List<Predicate> predicates,
                           List<string> cids)            

    {
        this.dateRange = dateRange;
        this.predicates = predicates;
        this.cids = cids;
    }
}

Dan sebut saja seperti ini:

  DataExtraction<AdPerformanceRow> extractor = new DataExtraction<AdPerformanceRow>(dates, predicates , cids);
Boris Detry
sumber