C#:定义一个接受N个布尔参数的委托,以便稍后提取参数名称

本文关键字:参数 提取 布尔 定义 一个 | 更新日期: 2023-09-27 18:29:36

我正在进行一个个人项目,以构建真值表生成器,重点是收集/巩固我所学到的关于逻辑等价的知识。

因此,我试图以一种C#函数作为参数的方式来编写它。稍后我将把它变成一个"构建编译器项目",但现在我想了解更多关于委托、元编程的知识,并在学习过程中享受逻辑等价的乐趣

所以,我想弄清楚的是,我将如何在语法上定义一个接受1到N个布尔参数的Delegate,这样我就可以避免像这样违反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类型的列表作为一个参数——当我想要的是一个可以接受带有两个布尔参数的布尔函数或带有1200布尔参数的函数的委托时。

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

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

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();
    }
}

如果你对我如何处理这个问题有任何建议(或者如果可能的话),我们将不胜感激

谢谢,

Chris

C#:定义一个接受N个布尔参数的委托,以便稍后提取参数名称

由于需要参数名称,所以会有点混乱。根据你想做的事情,你可以写这样的东西:

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 } });

您可以定义类似的param方法委托

 public delegate bool SumParameters(params bool[] values)

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

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

如果您只想获得有关该方法的一些信息,那么您需要的是一个接受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));