【问题标题】:Passing a variable name dynamically to a function将变量名动态传递给函数
【发布时间】:2013-10-09 14:17:27
【问题描述】:

我有这样的功能:

myFonction(ref List<string>myList)

我想用列表名称动态调用这个函数,像这样:

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
   ComboBox myCombo    =   (ComboBox)sender;    
   myFonction(ref "myList_" +  myCombo.SelectedItem.ToString());    
}

这可以用 C# 实现吗?

请问有没有办法做到这一点?

【问题讨论】:

  • 您能否更一般地解释一下您的应用程序需要做什么?对我来说,这是试图按照 .NET 的设计方式使用 .NET,因此可能有一个纯粹的解决方案可以解决您的问题。
  • 看看here希望对你有帮助
  • 你确定方法需要通过引用传递列表吗?鉴于列表是一种引用类型,您很少需要这样做。
  • 是的,我需要通过引用传递列表以便在我的函数中修改它们。
  • 您能后退一步,谈谈您为什么要这样做,以及它想要完成什么。这可能不是正确的方法,但我们没有足够的信息来真正提出正确的替代方案。

标签: c# .net winforms variables reflection


【解决方案1】:

你不能这样做,C# 是编译语言,而不是脚本语言。 您可以使用Dictionary&lt;string, List&lt;string&gt;&gt; _Lists 将列表保持在给定顺序并将它们传递给函数

myFunction(ref (from _Lists in _Lists where _List.Key == myCombo.SelectedItem.ToString() select _Lists.Value));

这不是最好的方法,但应该可以。

【讨论】:

  • 我不知道您为什么使用Dictionary 并使用循环(O(n) 操作)? _Lists[myCombo.SelectedItem.ToString()] 就够了
  • 另请注意,鉴于列表是通过引用传递的,这不起作用
  • C# 是否“编译”无关紧要。它支持反射,这正是他想做的事情。
【解决方案2】:

您可以使用反射。例如,如果所有的 myList_ 变量都是一个类的私有实例变量(比如定义这个偶数处理程序的表单),那么你可以这样做:

FieldInfo[] fields = MyForm.GetType().GetFields(
                     BindingFlags.NonPublic | 
                     BindingFlags.Instance);

然后,您必须寻找一个名称匹配的人。我认为有一种方法可以按名称查找成员,但我现在不记得了。请参阅http://msdn.microsoft.com/en-us/library/System.Type_methods.aspx 了解更多选项。

更传统的方法是创建一个将名称映射到列表对象的字典。您可以在表单加载时填充此字典,然后调用如下内容:

myFonction(dictionary["myList_" +  myCombo.SelectedItem.ToString()]);

当然,您不必手动填充字典:您可以在运行时使用反射(如上所示)来填充字典。然后,当您添加新列表时,您不必记住将其添加到字典中。您也可以使用相同的方法来填充组合框。

注意:我并不是说我一定要宽恕你正在做的事情作为一个好的设计原则。这并不意味着它不能完成。或者做得很好。或者讲道理。

编辑:我刚刚注意到您通话中的 ref (我复制并粘贴了您的代码)。我看不出有任何理由通过引用传递列表。无论如何,如果您从字典中获取它,则不能通过引用传递它——同样,您为什么要通过引用传递?

【讨论】:

  • 仍然不能使用 ref... 但是可以同时传递字典和键,从而允许被调用的方法在需要时更新存储的值
  • @BenVoigt 更好的办法是创建一个本地,通过 ref 传入 that,然后在方法调用后根据本地的结果修改字典。跨度>
  • @Jeremy,而不是使用GetFields 并找到具有正确名称的那个,只需使用GetField 并传入名称即可。此外,澄清问题应作为 cmets 发布,而不是在问题的答案中。
  • @Servy:这取决于更改何时需要对其他代码、回调等可见
  • 我猜是 OP 控制着这个功能。至少我希望没有人创建一个名为 myFonction 的通用/库函数。
【解决方案3】:

您可以通过使用 System.Reflection 动态提供其参数来调用您的方法。

例如:

public class SomeClass
{
    public void myFunction(ref List<string> myList)
    {
    }
}

public class SomeOtherClass
{
    public List<string> list1 { get; set; }
    public List<string> list2 { get; set; }
    public List<string> list3 { get; set; }

    public void DoSomething(int listNumber)
    {
        SomeClass someObject = new SomeClass();

        var parameter = typeof (SomeOtherClass).GetProperty("list" + listNumber).GetValue(this);
        typeof (SomeClass).GetMethod("myFunction").Invoke(someObject, new[] {parameter});
    }
}

【讨论】:

  • 没有理由使用反射调用myFonction。列表也不太可能(但可能)是属性;更有可能是字段。
  • 这不起作用,因为您的属性被声明为 private 而带有 1 个参数的 GetProperty 将仅搜索 public properties。要修复,请将private 更改为public 或使用更多BindingFlags
  • 是的,这段代码可能无法正常工作,但我在这里的目的是告诉大家上面的问题可以通过使用反射来解决。还应考虑性能问题,使用反射可能并不总是合适的。
【解决方案4】:

你应该可以这样做:

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
   ComboBox myCombo = (ComboBox)sender; 
   List<string> myList = new List<string>();
   myList.Add(myCombo.SelectedItem.ToString());
   myFonction(ref myList);    
}

【讨论】:

  • 他不想要一个被选中项的单一值的列表,他希望被选中的项在N个实例字段中选择成为一个方法中使用的列表。
  • @Servy 你是怎么得出这个结论的?这不是他要求或展示的。
  • myFonction(ref "myList_" + myCombo.SelectedItem.ToString()); 这表明他正在尝试
  • 他正在展示如何使用一个字符串来获取一个以它为标识符的变量,并将其标记为“反射”...
  • 他可能将其标记为反射,但这不是他所展示的。
猜你喜欢
  • 1970-01-01
  • 2017-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
  • 2020-07-28
相关资源
最近更新 更多