C# 使用枚举项调用方法
我有一个包含30项的枚举。每个项都有一个同名的对应函数。我希望能够通过在某个位置引用枚举来调用该函数 因此,如果C# 使用枚举项调用方法,c#,enums,C#,Enums,我有一个包含30项的枚举。每个项都有一个同名的对应函数。我希望能够通过在某个位置引用枚举来调用该函数 因此,如果enum[0]=Foo,我希望能够使用类似enum(0)(“foobar”)的东西调用Foo(字符串栏) 最后一点是,我将每个函数作为任务运行,如下所示: enum Test { AA, BB, CC, DD ....} tasks[0] = Task.Run(() => { prices[0] = AA("a string"); }); tasks[1] =
enum[0]=Foo
,我希望能够使用类似enum(0)(“foobar”)的东西调用Foo(字符串栏)
最后一点是,我将每个函数作为任务运行,如下所示:
enum Test { AA, BB, CC, DD ....}
tasks[0] = Task.Run(() => { prices[0] = AA("a string"); });
tasks[1] = Task.Run(() => { prices[1] = BB("a string"); });
tasks[2] = Task.Run(() => { prices[2] = CC("a string"); });
//for 30 tasks
我想做的事情大致如下:
enum Test { AA, BB, CC, DD ....}
for (int i = 0; i < 30; i++)
{
tasks[i] = Task.Run(() => { prices[i] = (Test)i("a string"); });
}
Task.WaitAll(tasks.ToArray());
我想我只是想让我的代码尽可能简洁,任务量可能会翻倍,我不想最后用60行来填充任务数组我会创建字典并将枚举映射到操作:
Dictionary<Test, Func<string,double>> actions = new Dictionary<Test, Func<string,double>>()
{
{Test.AA, (x) => { return 5;}},
{Test.BB, (x) => { return 15; }},
}; //x is your string
var res = actions[Test.AA]("hello");
字典操作=新建字典()
{
{Test.AA,(x)=>{return 5;}},
{Test.BB,(x)=>{return 15;}},
}; //x是你的字符串
var res=actions[Test.AA](“hello”);
我强烈建议使用内置构造-例如扩展方法和简单开关:
public static int GetPriceWithString(this Test test, string str)
{
switch (test)
{
case Test.AA:
break;
case Test.BB:
break;
case Test.CC:
break;
case Test.DD:
break;
default:
throw new ArgumentOutOfRangeException(nameof(test), test, null);
}
}
然后,您的循环看起来几乎相同:
for (int i = 0; i < 30; i++)
{
tasks[i] = Task.Run(() =>
{
prices[i] = ((Test)i).GetPriceWithString("a string");
});
}
for(int i=0;i<30;i++)
{
任务[i]=任务。运行(()=>
{
价格[i]=((测试)i).GetPriceWithString(“字符串”);
});
}
您想要做的是使用反射,反射可以是一个强大的工具,但理想情况下只能作为最后手段使用,因为它将隐藏可能的编译时错误,并导致代码可读性降低
使用这样一个简单的开关可以使您的代码自我记录,因此,当您在一个月后回到这里时,您可以很快记住其意图。使用一组代理如何:
using System;
using System.Threading.Tasks;
namespace ConsoleApplication
{
class Program
{
private static int AA(string a) { return 0; }
private static int BB(string a) { return 1; }
private static int CC(string a) { return 2; }
private static Func<string, int>[] functions = new Func<string, int>[] { AA, BB, CC };
private static int[] prices = new int[functions.Length];
private static Task[] tasks = new Task[functions.Length];
static void Main(string[] args)
{
for (int i = 0; i < functions.Length; ++i)
tasks[i] = Task.Run(() => { prices[i] = functions[i]("a string"); });
Task.WaitAll(tasks);
}
}
}
使用系统;
使用System.Threading.Tasks;
命名空间控制台应用程序
{
班级计划
{
私有静态int AA(字符串a){返回0;}
私有静态int-BB(字符串a){return 1;}
私有静态int CC(字符串a){return 2;}
私有静态Func[]函数=新的Func[]{AA,BB,CC};
私有静态int[]价格=新int[functions.Length];
私有静态任务[]任务=新任务[functions.Length];
静态void Main(字符串[]参数)
{
对于(int i=0;i{prices[i]=functions[i](“字符串”);});
Task.WaitAll(任务);
}
}
}
一个例子所说的远不止是文字
我在winform中使用了它,因此this
指的是win表单。
我假设您的所有方法都是公共的,具有相同的签名并返回相同的类型
enum MyName { AA,BB,CC};
//Call this in one of your methods
string [] strVal= Enum.GetNames(typeof(MyName));
int x = CallFunction(strVal[0], "A");
int y = CallFunction(strVal[1], "h");
int z = CallFunction(strVal[1], "C");
//End Call this in one of your methods
int CallFunction(string strName,string strValue)
{
return Convert.ToInt32(this.GetType().InvokeMember(strName, BindingFlags.Public | BindingFlags.InvokeMethod|BindingFlags.Instance, null, this, new object[] { strValue }));
}
public int AA(string s)
{
return 1;
}
public int BB(string s)
{
return 2;
}
public int CC(string s)
{
return 3;
}
另一个解决方案。我希望有人会认为这是过火的行为)
创建抽象类DealerBase
public abstract class DealerBase
{
public string Name { get; }
public decimal Price { get; set; }
protected DealerBase(string name)
{
Name = name;
}
public abstract void UpdatePrice();
}
然后为您拥有的每个经销商创建类,并为UpdatePrice
方法实现自己的逻辑
public class Dealer1 : DealerBase
{
public Dealer1() : base("DealerOne") { }
public override void UpdatePrice()
{
//Calculate price
Price = DealerOneCalculationMethod();
}
}
public class Dealer2 : DealerBase
{
public Dealer2() : base("DealerTwo") { }
public override void UpdatePrice()
{
//Calculate price
Price = DealerTwoCalculationMethod();
}
}
等等
然后,您只需创建可以轻松迭代的经销商集合
var dealers = new List<DealerBase>
{
new Dealer1(),
new Dealer2()
}
foreach(var dealer in dealers)
{
dealer.UpdatePrice();
}
您可以创建BindingList
并将其设置为DataGridView.DataSource
public class YourForm: Form
{
public YourForm()
{
InitializeComponent();
var dealers = new List<DealerBase>
{
new Dealer1(),
new Dealer2()
};
var bindSource = new BindingList<DealerBase>(dealers);
dataGridView.DataSource = bindSource;
}
// Add button which update prices for all dealers
private void ButtonUpdatePrices_Click(object sender, EventArgs e)
{
var dealers = (BindingList<DealerBase>)dataGridView.DataSource;
foreach (var dealer in dealers)
{
dealer.UpdatePrice();
// Because we call `RaisePropertyChanged` in
// setter of Price - prices will be automatically
// updated in DataGridView
}
}
}
公共类YourForm:Form
{
公共表格
{
初始化组件();
var交易商=新名单
{
新的Dealer1(),
新经销商2()
};
var bindSource=新绑定列表(经销商);
dataGridView.DataSource=bindSource;
}
//添加按钮,更新所有经销商的价格
私有无效按钮更新价格\u单击(对象发送者,事件参数e)
{
变量交易商=(BindingList)dataGridView.DataSource;
foreach(交易商中的var交易商)
{
dealer.UpdatePrice();
//因为我们把“RaisePropertyChanged”称为
//价格设定器-价格将自动
//在DataGridView中更新
}
}
}
这种方法的想法是,将不同经销商的不同逻辑放在单独的类中。因为所有经销商类都将从同一个抽象类继承,所以可以向集合中添加不同的经销商
您已经有了硬编码的枚举和相应的方法,尝试将它们链接在一起。这种方法使使用dealers collection little bid变得很容易您可以通过反射来实现这一点,但是您真的确定将函数名存储在枚举中是一个不错的选择吗?您必须使用反射来根据基于枚举值名称的方法名来查找MethodInfo
。然后可以使用反射来调用它。您可以将其封装在一个方法中,并通过传入枚举和参数来调用它。请注意,不同方法的参数不应不同。Noooooo!希望这不可能。这听起来像是XY的问题。你到底想达到什么目的?目前,您猜测一个enum和类似于enum的方法就是解决方案。但是如果我们知道你真正想做什么,可能会有一个更干净的方法。或者你可以创建一个字典查找并使用它。我假设它接受一个字符串参数并返回一个小数。@Igor:不要这样做。3年后,这个家伙将不再理解自己的源代码。代码期望输出,可能是十进制。Func
可能是一个更好的选择,而不是Action
。@Igor这只是一个例子,取决于OP想要实现什么。但是我同意回答这个问题应该有一个返回类型,我将编辑并可能使用int
作为键?似乎枚举的唯一值是为functions@KMoussa枚举还与表单上的文本框和标签相关,枚举的位置与prices数组的位置相关
var dealers = new List<DealerBase>
{
new Dealer1(),
new Dealer2()
}
foreach(var dealer in dealers)
{
dealer.UpdatePrice();
}
public abstract class DealerBase : INotifyPropertyChanged
{
public string Name { get; }
protected decimal _Price;
public decimal Price
{
get { return _Price; }
set
{
if (Equals(_Price, value)) return;
_Price = value;
// next method will inform DataGridView about changes
// and update value there too
RaisePropertyChanged();
}
protected DealerBase(string name)
{
Name = name;
}
public abstract void UpdatePrice();
// Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class YourForm: Form
{
public YourForm()
{
InitializeComponent();
var dealers = new List<DealerBase>
{
new Dealer1(),
new Dealer2()
};
var bindSource = new BindingList<DealerBase>(dealers);
dataGridView.DataSource = bindSource;
}
// Add button which update prices for all dealers
private void ButtonUpdatePrices_Click(object sender, EventArgs e)
{
var dealers = (BindingList<DealerBase>)dataGridView.DataSource;
foreach (var dealer in dealers)
{
dealer.UpdatePrice();
// Because we call `RaisePropertyChanged` in
// setter of Price - prices will be automatically
// updated in DataGridView
}
}
}