C#:定义一个带有N个布尔args的委托,以便稍后提取参数名

时间:2016-01-08 04:57:50

标签: c# delegates metaprogramming

我正在开发一个个人项目来构建一个真值表生成器,重点是收集/巩固我对逻辑等价学习的知识。

因此,我试图以一种 C#Function 作为参数的方式编写它。我稍后会把它变成"build a compiler project",但是现在我想要了解更多关于代表,元编程以及在逻辑等价方面的乐趣。

所以,我想弄清楚的是语法是如何定义一个需要1到N个布尔参数的委托,这样我就可以避免像这样违反DRY ......

public delegate bool OneArgFunc(bool arg1);

public delegate bool TwoArgFunc(bool arg1, bool arg2);

public delegate bool ThreeArgFunc(bool arg1, bool arg2, bool arg3);

public delegate bool OuchieThisIsStartingToHurt(bool arg, bool arg, bool arg...);

...而且我不相信下面会这样做,因为" ListOnlyFunc"将boolean类型的 list 作为单个参数 - 当我想要的是一个可以接受带有两个布尔参数的布尔函数的委托,或者一个带有1200个布尔参数的函数。

public delegate bool ListOnlyFunc(bool[] args); // Nope!

我想避免后者的部分原因是我希望能够从函数中提取参数名称(而不是显示通用的索引参数)。例如,如果我在下面运行,我应该看到" foo,baz,turkey"在输出窗口中;我不想简单地得到参数数量的计数并输出索引(" 1,2,3和#34;)。

public CSharpBoolDelegate MyFunc(bool foo, bool baz, bool turkey)
{
//does things
}

public class Program
{
    static void Main(string[] args)
    {
        IStatementSniffer sniffer = new CSharpFunctionSniffer(myFunc);

        sniffer.printArgs();

    }
}

如果您有任何关于如何处理此问题的提示(或者如果可能的话),我们将非常感谢您的建议。 :)

谢谢,

克里斯

3 个答案:

答案 0 :(得分:0)

你可以像这样定义param方法委托

 public delegate bool SumParameters(params bool[] values)

如果你想要参数的名字,你可以使用字典,这个解决方案已经由@Rob

提出
 public delegate bool SumParameters(Dictionary<string,bool> values)

答案 1 :(得分:0)

因为你想要参数名称,所以它有点乱。根据你想做的事情,你可以这样写:

public void MyFunc(bool? argOne = null, 
              bool? argTwo = null,
              bool? argThree = null,
              bool? argFour = null,
              bool? argFive = null)
{

}

你可以这样称呼它:

MyFunc(true);
MyFunc(true, false);
MyFunc(true, false, true);
MyFunc(true, false, true, false);

然而,这引起了一些并发症。例如,这是否有效?

MyFunc(null, true)

这里我们只提供了argTwo,但是你也必须提供所有以前的参数(例如,跳过参数无效)。

或者,您可以这样做:

public void MyFunc(Dictionary<string, bool> args)
{

}

并称之为:

 MyFunc(new Dictionary<string, bool> { { "arg1", true }, {"arg2", true } });

答案 2 :(得分:0)

如果您只想获得有关该方法的一些信息,那么您需要的是一个接受Delegate作为参数的方法:

public static string MethodSignature(Delegate del) => del.Method.ToString();

这样做的缺点是方法 Delegate(或delegate),因此您必须强制转换为Func<...>Action<...>或其他合适的代表类型,如下所示:

void Main()
{
    Console.WriteLine(MethodSignature((Func<bool, bool, bool>)testFunc));
    Console.WriteLine(MethodSignature((Action<bool, bool[]>)testAction));
}

bool testFunc(bool a, bool b) => a || b;

void testAction(bool a, bool[] b) { };

当然,如果您已经拥有delegate,则不需要演员。

无论哪种方式,一旦你有delegate参数名称可用:

public static string ParameterNames(Delegate del) => 
    string.Join(", ", del.Method.GetParameters().Select(p => p.Name));