C# Daftar Tindakan/Fungsi

Saya memiliki program yang harus menjalankan fungsi sesuai dengan Enum dan saya bertanya-tanya apakah ada cara lain selain ini:

enum FunctionType
{
 Addition = 0,
 Substraction = 1,
 Mutiplication = 2,
 Division = 3
}
void ExecuteFunction(FunctionType Function)
{
  switch(Function)
  {
    case FunctionType.Addition: Addition();
    break;
    case FunctionType.Substraction: Subsctration();
    break;      
    ...
    default: ...  
  }
}

(Ini bukan kode yang saya gunakan, ini hanya untuk mewakili apa yang ingin saya lakukan). Pendekatan ini seharusnya berfungsi dengan baik, tetapi apa yang terjadi jika Anda memiliki lebih banyak fungsi? Saya tidak ingin memiliki saklar 50 baris. Jadi saya ingin tahu apakah ada cara untuk menyederhanakannya, mungkin seperti ini:

enum FunctionType : Action
{
 Addition = new Action(Addition);
 Substraction = new Action(Substraction);
 ....
}
void ExecuteFunction(FunctionType Function)
{
 (Action)Function.Invoke();
}

Tidak diperlukan saklar dan apa yang bisa berupa 50 baris berubah menjadi 1 baris. Namun hal ini tidak mungkin dilakukan, hanya tipe numerik yang diterima sebagai enum. Saya pikir mungkin untuk memiliki List<T> tindakan tetapi itu memerlukan penambahan setiap tindakan ke daftar pada waktu runtime.

EDIT: Saya telah menemukan kode sumber cara melakukan hal ini, tetapi saya tidak dapat memahaminya. Inilah yang saya dapatkan: Mereka membuat Attribute khusus yang berisi string (Nama metode) dan metode yang mereka lakukan:

[CustomAtrribute("name")]
void Method()
{    
}

Lalu saya tidak tahu bagaimana ini disebut dengan namanya, saya kira semacam refleksi, tetapi saya tidak tahu bagaimana menemukan info tentang ini.

EDIT2: Saya menemukan cara yang saya inginkan untuk melakukan ini, saya akan menambahkan antarmuka dengan suatu fungsi, kemudian mengimplementasikan antarmuka itu dengan kode di dalam fungsi dan Gunakan Dictionary<Enum, Interface> untuk memanggilnya. Saya tidak tahu apakah saya harus menjawab pertanyaan saya sendiri, terima kasih kepada semua orang yang telah membantu saya.


person Pau C    schedule 19.08.2016    source sumber
comment
Anda dapat memiliki Dictionary<FunctionType, Action>... tetapi sekali lagi, Anda harus membangunnya pada waktu eksekusi. Jika semua nama metode cocok dengan nama nilai enum, Anda dapat melakukannya melalui refleksi.   -  person Jon Skeet    schedule 19.08.2016
comment
Anda dapat menjalankan suatu tindakan hanya dengan menambahkan (), tidak perlu melakukan .Invoke(). Sekadar informasi   -  person vrwim    schedule 19.08.2016
comment
@Jon Skeet Mungkin kamus berfungsi dengan baik, tetapi menambahkan semuanya kedengarannya tidak bagus. Masih lebih baik daripada saklar raksasa. Membuat setiap nama metode cocok dengan setiap nama enum terdengar sedikit berbahaya saat menambahkan hal baru   -  person Pau C    schedule 19.08.2016
comment
Tentu saja Anda bisa menambahkan unit test untuk itu. Pada akhirnya, Anda belum memberi tahu kami mengapa Anda memiliki enum untuk memulai. Mengapa metode ExecuteFunction Anda tidak hanya mengambil Action atau apa pun?   -  person Jon Skeet    schedule 19.08.2016
comment
Saya ingin melakukan ini di server dan setiap nilai dalam enum sesuai dengan jenis paket yang berbeda, setiap paket diidentifikasi dengan nilai int dan diuraikan ke dalam Enum. Dengan beberapa jenis paket yang berbeda, sebuah saklar akan baik-baik saja, tetapi ketika saya memperbarui program saya ingin menambahkan lebih banyak paket, dan saya ingin kodenya bersih, bukan saklar 50 kasus   -  person Pau C    schedule 19.08.2016
comment
Hati-hati, penguraian enum bisa jadi rumit: stackoverflow.com/questions/28219215/   -  person argyle    schedule 19.08.2016
comment
Saya baru saja mentransmisikannya dari int, dan saya periksa dulu apakah nilainya ada. Tapi terima kasih.   -  person Pau C    schedule 19.08.2016


Jawaban (2)


Saya tidak bisa mengatakan saya akan merekomendasikan melakukan ini tetapi:

public static class Functions
{
    public static Func<int, int, int> Add = (x, y) => { return x + y; };
}

Lalu kamu tinggal menelpon Functions.Add(1,1)

Jika Anda benar-benar harus menggunakan enum maka Anda dapat melakukan:

public static class Functions
{
    public static void Add()
    {
        Debug.Print("Add");
    }

    public static void Subtract()
    {
        Debug.Print("Subtract");
    }

    public enum Function
    {
        Add,
        Subtract
    }

    public static void Execute(Function function)
    {
        typeof(Functions).GetMethod(function.ToString()).Invoke(null, null);
    }
}

Kemudian Functions.Execute(Functions.Function.Add) (fungsi tambahan karena enum saya ada di dalam kelas Fungsi).

person Dave Williams    schedule 19.08.2016
comment
Kelihatannya menarik, tapi apakah ini akan berdampak pada performa jika dipanggil berkali-kali? Juga mengapa .Invoke(null, null);? - person Pau C; 19.08.2016
comment
Saya menguji ini dan dampak kinerjanya cukup besar, Dibutuhkan waktu x30 jika saya memasukkan nama fungsi sebagai string dan x133 jika saya melakukan .ToString() membandingkan pemanggilan fungsi biasa. Jika saya memuat methodInfo terlebih dahulu dibutuhkan waktu x20. - person Pau C; 19.08.2016
comment
@null .Invoke(null,null) untuk memanggil metode statis tanpa argumen, Anda mungkin perlu mengubahnya sesuai kebutuhan Anda. Performa yang menggunakan refleksi akan sangat terpengaruh. Aku sudah bilang, aku menyarankanmu untuk tidak melakukannya. Mungkin ada baiknya memeriksa apakah Anda melakukannya dengan cara yang benar jika Anda merasa perlu refleksi. Saya hanya dapat menjawab pertanyaan Anda karena saya tidak tahu apa yang ingin Anda capai. Meskipun demikian, penalti kinerja mungkin dapat diterima tergantung pada situasi Anda. Jangan optimalkan sebelum waktunya. - person Dave Williams; 21.08.2016
comment
Saya menemukan cara untuk melakukan apa yang saya inginkan, saya menetapkan atribut khusus dengan string ke fungsi lalu saya menggunakan refleksi untuk mendapatkan semua fungsi dengan atribut itu dan menambahkan ke string Kamus, delegasi› jadi tidak ada masalah besar dampak kinerja, karena saya hanya menggunakan refleksi sekali. - person Pau C; 22.08.2016

Jika fungsi Anda berisi signature yang sama maka Anda dapat melakukan sesuatu seperti ini

enum FunctionType
{
 Addition = 0,
 Substraction = 1,
 Mutiplication = 2,
 Division = 3
}
void ExecuteFunction(FunctionType Function)
{
  //variable will contain function to execute
  public Func<int, int, int> functionToExecute= null;

  switch(Function)
  {
    case FunctionType.Addition: functionToExecute=Addition;
    break;
    case FunctionType.Substraction: functionToExecute=Subsctration;
    break;      
    ...
    default: ...  
  }

  //Checking if not reached default case
  if(functionToExecute!=null)
  {
   var result= functionToExecute(para1,para2);
   ...............
  }


}
person Moumit    schedule 19.08.2016
comment
Saya mencoba menghindari peralihan, itulah masalahnya. Jika saya memiliki banyak fungsi, kodenya akan terlalu panjang. - person Pau C; 19.08.2016