参数动作其中T3可选

发布于 2024-12-08 11:43:12 字数 961 浏览 0 评论 0原文

我有以下代码:

public static MyMethod()  
{ 
   ...Do something  
   ProtectedMethod(param1, param2);  
   ...Do something  
}  

protected static void ProtectedMethod(IEnumerable<string> param1, string param2, int param3 = 1)  
{  
   ... Do something  
}

注意可选的 param3 参数。

现在,由于多种原因,我需要将 MyMethod 方法的代码提取到它自己的类中,但我无法用它提取 ProtectedMethod ,因为所有从该类继承的类,我需要保持更改较小且孤立。所以我想我可以有一个 Action<>新类中的委托具有与 ProtectedMethod 相同的签名。

问题是,如果我像这样声明委托:

protected readonly Action<IEnumerable<string>, string, int> m_ProtectedMethod;

提取的代码不喜欢它,因为它说该方法仅使用两个参数调用。

如果我像这样声明委托:

protected readonly Action<IEnumerable<string>, string> m_ProtectedMethod;

当我将它作为参数发送给新类时,它也不喜欢它,因为该方法被定义为具有三个参数而不是两个。

到目前为止,我想到解决此问题的唯一方法是创建 ProtectedMethod 的重载版本以消除可选参数。

这是唯一的选择还是有其他方法可以做到这一点,因为现在首选是使用可选参数而不是重载方法?

I have the following code:

public static MyMethod()  
{ 
   ...Do something  
   ProtectedMethod(param1, param2);  
   ...Do something  
}  

protected static void ProtectedMethod(IEnumerable<string> param1, string param2, int param3 = 1)  
{  
   ... Do something  
}

Take notice of the optional param3 parameter.

Now for quite a few reasons I need to extract the code of the MyMethod method into its own class but I cannot extract ProtectedMethod with it because of all the classes that are inheriting from this one and I need to keep the changes small and isolated. So I figured I could have an Action<> delegate in the new class with the same signature as ProtectedMethod.

The problem is that if I declare the delegate like this:

protected readonly Action<IEnumerable<string>, string, int> m_ProtectedMethod;

The extracted code does not like it because it says the method is only being invoked with two parameters.

And if I declare the delegate like so:

protected readonly Action<IEnumerable<string>, string> m_ProtectedMethod;

When I send it as a parameter to the new class it does not like it either because the method is defined as having three parameters not two.

So far the only way I have thought of to solve this is to create an overloaded version of ProtectedMethod to eliminate the optional parameter.

Is this the only option or is there another way of doing it since now the preferred choice is to have optional parameters instead of overloaded methods?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

榆西 2024-12-15 11:43:12

可选参数是方法或委托参数的属性。当您在编译时调用具有已知可选参数的签名(方法或委托)时,编译器将在调用站点插入可选参数值。

运行时不知道可选参数,因此您无法创建在调用时插入可选参数的委托。

相反,您需要使用可选参数声明自定义委托类型:

public delegate void MyDelegate(IEnumerable<string> param1, string param2, int param3 = 1);

调用此委托时,您将能够省略第三个参数,无论它包含的方法的声明如何。

Optional parameters are an attribute of a method or delegate parameter. When you call a signature (method or delegate) that has a known optional parameter at compile-time, the compiler will insert the optional parameter value at the callsite.

The runtime is not aware of optional parameters, so you can't make a delegate that inserts an optional parameter when it's called.

Instead, you need to declare a custom delegate type with an optional parameter:

public delegate void MyDelegate(IEnumerable<string> param1, string param2, int param3 = 1);

When calling this delegate, you will be able to omit the third parameter, regardless of the declaration of the method(s) it contains.

看海 2024-12-15 11:43:12

这取决于 m_ProtectedMethod 的使用方式,但我在自己的情况下找到了一种折衷方案,即我使用一个重载多于另一个重载。

只需定义一个更简单(具有较少通用参数)的操作变量,它调用更复杂的提供的 Action 变量方法。这可以在(i)本地使用范围内完成; (ii) Action 属性分配或对象构造时的对象范围。

因为不存在变量/属性重载之类的东西,所以您需要两个不同的名称来表示生成的两个相关的操作变量。

EG i:本地作用域(可能不是最适合您的场景)

public MyMethod(Action<IEnumerable<string>, string, int> m_ProtectedMethod2)  
{ 
   Action<IEnumerable<string>, string> m_ProtectedMethod = (p1,p2) => {
      m_ProtectedMethod2(p1,p2,1); //The value 1 is the default 3rd parameter
   }

   ...Do something  
   m_ProtectedMethod(param1, param2);  
   ...Do something  
   ...If something  
      m_ProtectedMethod2(param1, param2, param3); //Calling the more complex form directly
   ...Do something  
}  

EG ii:对象作用域

private Action<IEnumerable<string>, string, int> m_ProtectedMethod2 = null;
private Action<IEnumerable<string>, string> m_ProtectedMethod = null;
protected Action<IEnumerable<string>, string, int> ProtectedMethod
{
   get { return m_ProtectedMethod2; }
   set {
      m_ProtectedMethod2 = value;
      m_ProtectedMethod = (p1,p2) => {
         m_ProtectedMethod2(p1,p2,1); //The value 1 is the default 3rd parameter
      }
   }
}

public MyMethod()
{
   ...Do something  
   m_ProtectedMethod(param1, param2);  
   ...Do something  
   ...If something  
      m_ProtectedMethod2(param1, param2, param3); //Calling the more complex form directly
   ...Do something  
}

注意,在这两种情况下,我将默认设置值设计为更尴尬的命名变量,具有 2 后缀,以便在使用时更简单的重载具有更基本的变量名称。

It would depend on how m_ProtectedMethod would be consumed, but I found a compromise in my own situation, where I use one overload more than the other.

Simply define a simpler (having less generic parameters) Action<> variable, which calls the more complex supplied Action variable method. This can be accomplished either in (i) local scope on use; or (ii) object scope upon assignment of Action property or object construction.

Because there is no such thing as variable/property overloading, you need two different names, for the resulting two related Action variables.

EG i: Local Scope (probably not the most suitable for your scenario)

public MyMethod(Action<IEnumerable<string>, string, int> m_ProtectedMethod2)  
{ 
   Action<IEnumerable<string>, string> m_ProtectedMethod = (p1,p2) => {
      m_ProtectedMethod2(p1,p2,1); //The value 1 is the default 3rd parameter
   }

   ...Do something  
   m_ProtectedMethod(param1, param2);  
   ...Do something  
   ...If something  
      m_ProtectedMethod2(param1, param2, param3); //Calling the more complex form directly
   ...Do something  
}  

EG ii: Object Scope

private Action<IEnumerable<string>, string, int> m_ProtectedMethod2 = null;
private Action<IEnumerable<string>, string> m_ProtectedMethod = null;
protected Action<IEnumerable<string>, string, int> ProtectedMethod
{
   get { return m_ProtectedMethod2; }
   set {
      m_ProtectedMethod2 = value;
      m_ProtectedMethod = (p1,p2) => {
         m_ProtectedMethod2(p1,p2,1); //The value 1 is the default 3rd parameter
      }
   }
}

public MyMethod()
{
   ...Do something  
   m_ProtectedMethod(param1, param2);  
   ...Do something  
   ...If something  
      m_ProtectedMethod2(param1, param2, param3); //Calling the more complex form directly
   ...Do something  
}

Note in both cases I designed the default setting value to be the more awkwardly named variable, having the 2 suffix, such that upon consumption the simpler overload has the more basic variable name.

毁虫ゝ 2024-12-15 11:43:12

希望能够帮助其他人,我发现这是一种与(面向委托的)策略模式混合的更优雅的重载实现。

public class OverloadExample {
    private Action<int, bool> _implementation;

    public OverloadExample() {
        _implementation = defaultImplementation;
    }

    public OverloadExample(Action<int, bool> implementation) {
        _implementation = implementation;
    }

    protected void defaultImplementation(int aInt, bool aBool) {
        //
    }

    public void Implementation(int someInt, bool someBool = true) {
        _implementation(someInt, someBool);
    }
}

用法:

new OverloadExample().Implementation(9001);
new OverloadExample().Implementation(9001, false);

Hoping to help others with what I find as being a more elegant implementation of overloading mixed with the (delegate-oriented) strategy pattern.

public class OverloadExample {
    private Action<int, bool> _implementation;

    public OverloadExample() {
        _implementation = defaultImplementation;
    }

    public OverloadExample(Action<int, bool> implementation) {
        _implementation = implementation;
    }

    protected void defaultImplementation(int aInt, bool aBool) {
        //
    }

    public void Implementation(int someInt, bool someBool = true) {
        _implementation(someInt, someBool);
    }
}

Usage:

new OverloadExample().Implementation(9001);
new OverloadExample().Implementation(9001, false);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文