是否可以在 C# 中使用条件参数

本文关键字:条件 参数 是否 | 更新日期: 2023-09-27 18:37:24

编辑:
如果您来到这里寻找快速答案:可以这样做,但函数的概述没有显示我正在寻找的结果。

Aidin 的答案"代码合同"会给出一个错误,如果你省略了一个可选但必需的(因为......)参数。这似乎是将其强加给用户的最简单方法,但需要向函数的用户进行一些解释。

Shawn Holzworth 的答案"将逻辑放在类中"符合我的需求,即轻松向函数的用户展示他们有哪些选项,但它需要不同的方法和大量的代码重写。


我正在尝试创建一个接受不同参数集的函数。在代码中,我检查给定了哪组参数,并在此基础上对 URL 执行某些操作,以便从保险公司接收一组包含个人信息的值(这就是为什么没有其他代码的原因)。在谷歌上搜索没有给出使参数相互条件的结果,因此我不确定这是否可能。
基本上这个想法是有一个这样的函数调用:

  dobFormatted
, infodateFormatted
, (BSN | insuranceID | lastname | postalcode, Homenummer[, Homenummeradd])
[, insuranceType]

允许以下列方式使用该函数:

  • dobFormatted, infodateFormatted, BSN
  • dobFormatted, infodateFormatted, BSN, insuranceType
  • dobFormatted, infodateFormatted, insuranceID
  • dobFormatted, infodateFormatted, insuranceID, insuranceType
  • dobFormatted, infodateFormatted, lastname
  • dobFormatted, infodateFormatted, lastname, insuranceType
  • dobFormatted, infodateFormatted, postalcode, Homenummer
  • dobFormatted, infodateFormatted, postalcode, Homenummer, insuranceType
  • dobFormatted, infodateFormatted, postalcode, Homenummer, Homenummeradd
  • dobFormatted, infodateFormatted, postalcode, Homenummer, Homenummeradd, insuranceType

因此,代码强制调用函数以包含所需的信息。我知道这可以通过创建需要不同参数集的函数的多个版本并返回当前函数的输出来实现。但是,我认为这将使代码的可读性和可维护性降低。此外,还有 3 种方法可以仅使用 3 个字符串完成函数,但输出取决于第 3 个参数。


目前我有这个代码:

public static string getVecozoURL(string dobFormatted, string infodateFormatted, 
        string BSN = "", string insuranceID= "", string lastname= "",
        string postalcode = "", int Homenummer = 0, string Homenummeradd = "",
        string insuranceType = "Both") {
    string URL= "";
    if (FCelfproef.BSN(BSN)) {
        // Do stuff
    } else if (!insuranceID.IsEmpty()) {
        // Do stuff
    } else if (postalcode .Length > 4 && Homenummer > 0) {
        // Do stuff
    } else if (!lastname.IsEmpty()) {
        // Do stuff
    }
    // Do some other stuff
    return URL;
}

有没有一种简单的方法来强制这样做,或者我是否必须通知所有将使用它的人有关该功能的工作方式?

是否可以在 C# 中使用条件参数

您可以在 C sharp 中创建具有单独重载的方法签名

public void TestMethod(string stringValue, int intValue)
public void TestMethod(double doubleValue, int intValue)
public void TestMethod(string stringValue, string otherStringValue)   
public void TestMethod(string stringValue, int intValue, string otherStringValue)

这些都可以称为单独的方法。

重载


同样在 C 尖锐中,您可以使用可选参数。

public void TestMethod(int intValue
                      ,int optionalIntValue = 0
                      ,int optionalSecondValue = 4)

你可以打电话给喜欢的地方

TestMethod(1) 
//optionalValue = 0(default) & optionalSecondValue = 4(default)
TestMethod(1, optionalSecondValue:2) 
//optionalValue = 0(default) & optionalSecondValue = 2
TestMethod(1, 12) 
//optionalValue = 12 & optionalSecondValue = 4(default)

由于方法参数共享类型重载,因此单个方法会遇到麻烦。要使这些调用成为唯一允许的调用,您需要为每个调用使用单独的方法。

public static string getVecozoURL_BSN(string dobFormatted, string infodateFormatted, string BSN, string insuranceType = "Both")
public static string getVecozoURL_InsurranceID(string dobFormatted, string infodateFormatted, string insuranceID, string insuranceType = "Both")
public static string getVecozoURL_Lastname(string dobFormatted, string infodateFormatted, string lastname, string insuranceType = "Both")
public static string getVecozoURL_Postalcode(string dobFormatted, string infodateFormatted, string postalcode, int Homenummer, string Homenummeradd = "", string insuranceType = "Both")

但是,由于您关心的是可读性/可维护性,因此将逻辑封装在它自己的类中可能更有意义。 像这样:

class VecozoURLFormater
{
    public string DobFormatted { get; private set; }
    public string InfodateFormatted { get; private set; }
    public string InsuranceType { get; private set; }
    public VecozoURLFormater(string dobFormatted, string infodateFormatted, string insuranceType = "Both")
    {
        DobFormatted = dobFormatted;
        InfodateFormatted = infodateFormatted;
        InsuranceType = insuranceType;
    }
    public string FromBSN(string BSN){/*...*/}
    public string FromInsurranceID(string insuranceID){/*...*/}
    public string FromLastname(string lastname){/*...*/}
    public string FromPostalcode(string postalcode, int Homenummer, string Homenummeradd = "") {/*...*/}
}

所有这些解决方案都很棒,只要你愿意重载你的函数。我个人会超载该功能;但是,如果您坚持只使用一个函数,那么我强烈建议您使用代码协定来强制使用任何参数组合所需的任何逻辑。下面是一个示例:

public string XYZ(string dobFormatted, string infodateFormatted, 
        string BSN = "", string insuranceID= "", string lastname= "",
        string postalcode = "", int Homenummer = 0, string Homenummeradd = "",
        string insuranceType = "Both")
{
    Contract.Requires(!string.IsNullOrEmpty(dobFormatted) || insuranceType == "NONE");    
}

您可以根据需要拥有任意数量的 Requires() 函数。您可以启用代码协定的静态检查,编译器可以在您危及约束时向您发出警告。

访问 http://msdn.microsoft.com/en-us/library/dd264808.aspx 了解更多信息。

请记住,即使在重载函数中也可以使用代码协定。

您可以重新设计方法以接受您定义的包含所有这些信息的类的对象,或者您可以创建具有不同参数的多个方法,基本上是重载它或不同的方法。

我不认为你可以有基于另一个参数的值的条件参数,因为如果这个参数在那里,那么不需要另一个,依此类推......

该方法的重载链接在一起就是您的答案。 这将允许每个人按照自己喜欢的方式管理它。

我在下面的示例中返回了链的字符串,但您可以轻松地将逻辑添加到每个方法中,这样您就不会在末尾出现令人讨厌的 if 语句。

    public static string getVecozoURL(string dobFormatted, string infodateFormatted, string BSN)
    {
        return getVecozoURL(dobFormatted, infodateFormatted, BSN, "", "", "", 0, "", "Both");
    }
    public static string getVecozoURL(string dobFormatted, string infodateFormatted, string BSN, string insuranceID)
    {
        return getVecozoURL(dobFormatted, infodateFormatted, BSN, insuranceID, "", "", 0, "", "Both");
    }
    public static string getVecozoURL(string dobFormatted, string infodateFormatted, string BSN, string postalcode, int Homenummer)
    {
        return getVecozoURL(dobFormatted, infodateFormatted, BSN, "", "", postalcode, Homenummer, "", "Both");
    }
    public static string getVecozoURL(string dobFormatted, string infodateFormatted,
    string BSN, string insuranceID, string lastname,
    string postalcode, int Homenummer, string Homenummeradd,
    string insuranceType)
    {
        string URL = "";
        if (FCelfproef.BSN(BSN))
        {
            // Do stuff
        }
        else if (!insuranceID.IsEmpty())
        {
            // Do stuff
        }
        else if (postalcode.Length > 4 && Homenummer > 0)
        {
            // Do stuff
        }
        else if (!lastname.IsEmpty())
        {
            // Do stuff
        }
        // Do some other stuff
        return URL;
    }

试试这种方法:

public enum VecozoOverloadedOptions { BSN, InsuranceID, LastName, PostalCode };
public class VecozoValues
{
    public string DobFormatted;
    public string infodateFormatted;
    public VecozoOverloadedOptions OverloadChoice;
    public string OverloadedValue;
    public int Homenummer;
    public string Homenummeradd;
    public string InsuranceType;
}
...
public static string getVecozoURL(VecozoValues data)
{
   ...

这种类型的问题通常最好用流畅的语法来解决:

public class VecozoURLBuilder
{
    private string _dobFormatted;
    private string _infodateFormatted;
    private string _bsn;
    private string _insuranceID;
    ...
    public VecozoURLBuilder DobFormatted(string dobFormatted)
    {
        _dobFormatted = dobFormatted;
        return this;
    }
    public VecozoURLBuilder InfodateFormatted(string infodateFormatted)
    {
        _infodateFormatted= nfodateFormatted;
        return this;
    }
    ...
    public string VecozoURL()
    {
        // create string from dobFormatted  etc.
    }
}

然后像这样使用它:

var url = new VecozoURLBuilder()
    .DobFormatted("xxx")
    .InfodateFormatted("yyy")
    .VecozoURL();

显然,完整的内容将具有问题中所有必需值的字段和所有字段的流畅方法。