C# 修改helper类中的方法

C# 修改helper类中的方法,c#,C#,最近我遇到了一个我不太确定的问题。情况是: 假设我们有一个helper类:H,helper类M1(inta,intb,intc)中的一个方法接受三个参数。有三类使用此方法:C1、C2、C3 现在,我们需要另一个类C4,它也使用方法M1,将传递四个参数,而不是三个 那么,我们如何解决这个问题呢 我们需要扩展方法吗?您可以使用默认参数重载M1()方法: public static void M1(int a, int b, int c, int? d = null) { // working

最近我遇到了一个我不太确定的问题。情况是:

假设我们有一个helper类:H,helper类M1(inta,intb,intc)中的一个方法接受三个参数。有三类使用此方法:C1、C2、C3

现在,我们需要另一个类C4,它也使用方法M1,将传递四个参数,而不是三个

那么,我们如何解决这个问题呢


我们需要扩展方法吗?

您可以使用默认参数重载
M1()
方法:

public static void M1(int a, int b, int c, int? d = null)
{
    // working with a, b, c

    if (d == null)
        return;

    var dValue = (int)d; // casting the nullable int to int to work with

    // use the d parameter
}
在C1、C2、C3中,您将调用:

H1(1, 2, 3);
H1(1, 2, 3, 4);
在C4中,您将调用:

H1(1, 2, 3);
H1(1, 2, 3, 4);

注意:
int?
使输入参数
可为空
,因此您可以将其设置为
null
。这样,您就不必选择一个数字作为默认参数(也可以有意传递)。

您可以使用默认参数重载
M1()
方法:

public static void M1(int a, int b, int c, int? d = null)
{
    // working with a, b, c

    if (d == null)
        return;

    var dValue = (int)d; // casting the nullable int to int to work with

    // use the d parameter
}
在C1、C2、C3中,您将调用:

H1(1, 2, 3);
H1(1, 2, 3, 4);
在C4中,您将调用:

H1(1, 2, 3);
H1(1, 2, 3, 4);

注意:
int?
使输入参数
可为空
,因此您可以将其设置为
null
。这样,您就不必选择一个数字作为默认参数(也可以故意传递)。

您可以使用默认参数,但问题是C1、C2和C3也会使用4个参数获得重载,而C4会使用3个参数获得重载。你陈述问题的方式,我猜这是没有意义的(尤其是带有3个参数的C4在现实设计中通常没有意义)

前进的方向是引入一个受保护的成员并转发呼叫。基本上,您的代码如下所示:

public class BaseClass 
{
    protected void H1B(int a, int b, int c, int d) { ... }
}

public class BaseClassFor3 : BaseClass
{
    public void H1(int a, int b, int c) { H1B(a,b,c,0); } // forward call
}

public class C1 : BaseClassFor3 {} // etc
public class C2 : BaseClassFor3 {} // etc 
public class C3 : BaseClassFor3 {} // etc

public class C4 : BaseClass
{
    public void H1(int a, int b, int c, int d) { H1B(a,b,c,d); } // forward call
}
public void H1(int a, int b, int c, int d) 
{
    // NOTE: this is just an example, I'd normally use an OR mapper!

    // Construct query using a,b,c
    string baseQuery = ConstructQuery(a,b,c);
    baseQuery += " and d = " + d.ToString();

    // ...
    ExecuteSql(baseQuery);

    // ...
}
添加一个可为空或一个参数

现在@KAI提出了一个棘手的问题:在什么情况下添加
int?d
还是另一个过载?来吧

根据经验,我总是试图使一个类的功能独立于其他类的功能。这基本上意味着,如果有C4,基类中的代码不应该检查子类(如C4)隐含的条件

那么我们可以这样说:

public void H1(int a, int b, int c, int? d) //...
通常,这意味着在某个地方我们会得到以下代码:

if (d.HasValue) 
{ 
    // handle something that's specific for C4
}
因为这打破了独立性的观念,我永远不会赞成

现在有两种选择:

  • H1调用实现共享相同的名称(因为在使用类时这很容易理解),但在其他方面彼此几乎没有共同之处
  • H1调用实现共享许多相同的代码(除了名称) 作为(1)的一个例子:如果你熟悉f.ex。在PDF应用程序中,C1-C4实际上可能是4x4矩阵上的向量运算。在这种情况下,有些操作有3个操作数,有些操作有4个操作数。在省略操作数的情况下,我们通常隐式地表示
    0

    在本例中,我们添加了一个带有
    int
    的公共受保护基类,并像上面那样实现它。注意,基类的代码中没有
    if
    ;它的功能在基类中是隔离的,就像它应该的那样

    在这种情况下,我也会使用一个
    Nullable
    ——但是如果你开始这样想,你会注意到Nullable将非常非常罕见

    在场景(2)中,答案是不同的。例如,假设H1在数据库中插入了一些内容。实现两次共享代码或复制粘贴共享代码没有什么意义。最好隔离代码,创建一个单独的方法,并从3/4参数实现中调用它。可能会是这样的:

    public class BaseClass 
    {
        protected void H1B(int a, int b, int c, int d) { ... }
    }
    
    public class BaseClassFor3 : BaseClass
    {
        public void H1(int a, int b, int c) { H1B(a,b,c,0); } // forward call
    }
    
    public class C1 : BaseClassFor3 {} // etc
    public class C2 : BaseClassFor3 {} // etc 
    public class C3 : BaseClassFor3 {} // etc
    
    public class C4 : BaseClass
    {
        public void H1(int a, int b, int c, int d) { H1B(a,b,c,d); } // forward call
    }
    
    public void H1(int a, int b, int c, int d) 
    {
        // NOTE: this is just an example, I'd normally use an OR mapper!
    
        // Construct query using a,b,c
        string baseQuery = ConstructQuery(a,b,c);
        baseQuery += " and d = " + d.ToString();
    
        // ...
        ExecuteSql(baseQuery);
    
        // ...
    }
    

    您可以使用默认参数,但问题是C1、C2和C3也会得到带有4个参数的重载,而C4会得到带有3个参数的重载。你陈述问题的方式,我猜这是没有意义的(尤其是带有3个参数的C4在现实设计中通常没有意义)

    前进的方向是引入一个受保护的成员并转发呼叫。基本上,您的代码如下所示:

    public class BaseClass 
    {
        protected void H1B(int a, int b, int c, int d) { ... }
    }
    
    public class BaseClassFor3 : BaseClass
    {
        public void H1(int a, int b, int c) { H1B(a,b,c,0); } // forward call
    }
    
    public class C1 : BaseClassFor3 {} // etc
    public class C2 : BaseClassFor3 {} // etc 
    public class C3 : BaseClassFor3 {} // etc
    
    public class C4 : BaseClass
    {
        public void H1(int a, int b, int c, int d) { H1B(a,b,c,d); } // forward call
    }
    
    public void H1(int a, int b, int c, int d) 
    {
        // NOTE: this is just an example, I'd normally use an OR mapper!
    
        // Construct query using a,b,c
        string baseQuery = ConstructQuery(a,b,c);
        baseQuery += " and d = " + d.ToString();
    
        // ...
        ExecuteSql(baseQuery);
    
        // ...
    }
    
    添加一个可为空或一个参数

    现在@KAI提出了一个棘手的问题:在什么情况下添加
    int?d
    还是另一个过载?来吧

    根据经验,我总是试图使一个类的功能独立于其他类的功能。这基本上意味着,如果有C4,基类中的代码不应该检查子类(如C4)隐含的条件

    那么我们可以这样说:

    public void H1(int a, int b, int c, int? d) //...
    
    通常,这意味着在某个地方我们会得到以下代码:

    if (d.HasValue) 
    { 
        // handle something that's specific for C4
    }
    
    因为这打破了独立性的观念,我永远不会赞成

    现在有两种选择:

  • H1调用实现共享相同的名称(因为在使用类时这很容易理解),但在其他方面彼此几乎没有共同之处
  • H1调用实现共享许多相同的代码(除了名称) 作为(1)的一个例子:如果你熟悉f.ex。在PDF应用程序中,C1-C4实际上可能是4x4矩阵上的向量运算。在这种情况下,有些操作有3个操作数,有些操作有4个操作数。在省略操作数的情况下,我们通常隐式地表示
    0

    在本例中,我们添加了一个带有
    int
    的公共受保护基类,并像上面那样实现它。注意,基类的代码中没有
    if
    ;它的功能在基类中是隔离的,就像它应该的那样

    在这种情况下,我也会使用一个
    Nullable
    ——但是如果你开始这样想,你会注意到Nullable将非常非常罕见

    在场景(2)中,答案是不同的。例如,假设H1插入了somet