Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
您应该在C#4.0中声明使用重载或可选参数的方法吗?_C#_C# 4.0_Overloading_Optional Parameters - Fatal编程技术网

您应该在C#4.0中声明使用重载或可选参数的方法吗?

您应该在C#4.0中声明使用重载或可选参数的方法吗?,c#,c#-4.0,overloading,optional-parameters,C#,C# 4.0,Overloading,Optional Parameters,我一直在看,这让我思考在C#中何时可以使用可选参数?对于不需要指定所有参数的方法,推荐的声明方法是什么 例如,FileStream类有大约15个不同的构造函数,这些构造函数可以分为逻辑“族”,例如,字符串下面的构造函数、IntPtr中的构造函数和SafeFileHandle中的构造函数 FileStream(string,FileMode); FileStream(string,FileMode,FileAccess); FileStream(string,FileMode,FileAccess

我一直在看,这让我思考在C#中何时可以使用可选参数?对于不需要指定所有参数的方法,推荐的声明方法是什么

例如,
FileStream
类有大约15个不同的构造函数,这些构造函数可以分为逻辑“族”,例如,字符串下面的构造函数、IntPtr中的构造函数和SafeFileHandle中的构造函数

FileStream(string,FileMode);
FileStream(string,FileMode,FileAccess);
FileStream(string,FileMode,FileAccess,FileShare);
FileStream(string,FileMode,FileAccess,FileShare,int);
FileStream(string,FileMode,FileAccess,FileShare,int,bool);
在我看来,这种类型的模式可以通过使用三个构造函数来简化,并对可以默认的构造函数使用可选参数,这将使不同的构造函数族更加不同[注:我知道BCL中不会进行这种更改,我是在假设这种情况下说的]


你觉得怎么样?从C#4.0开始,将密切相关的构造函数和方法组设置为具有可选参数的单个方法是否更有意义,或者是否有充分的理由坚持传统的多重载机制?

当方法重载通常使用不同数量的参数执行相同的操作时,将使用默认值

当方法重载根据其参数执行不同的函数时,将继续使用重载


早在VB6时代,我就使用了可选参数,但后来错过了它,它将减少C#中大量的XML注释重复。

我期待使用可选参数,因为它保留了默认值更接近该方法的参数。因此,与只调用“expanded”方法的几十行重载不同,您只需定义一次方法,就可以在方法签名中看到可选参数的默认值。我宁愿看看:

public Rectangle (Point start = Point.Zero, int width, int height)
{
    Start = start;
    Width = width;
    Height = height;
}
与此相反:

public Rectangle (Point start, int width, int height)
{
    Start = start;
    Width = width;
    Height = height;
}

public Rectangle (int width, int height) :
    this (Point.Zero, width, height)
{
}

显然,这个例子很简单,但是在OP中有5个重载的情况下,事情会变得很快很快。

< P>我会考虑以下内容:

  • 您是否需要从不支持可选参数的语言中使用代码?如果是,请考虑包含重载。
  • 您的团队中是否有任何成员强烈反对可选参数?(有时候,接受一个你不喜欢的决定要比争辩更容易。)
  • 您确信您的默认值不会在代码的不同版本之间更改吗?或者,如果可能的话,您的调用者会同意吗

我没有检查默认值是如何工作的,但是我假设默认值将被烘焙到调用代码中,这与对
const
字段的引用非常相似。这通常是好的——无论如何,更改默认值是非常重要的,但是这些是要考虑的事情。

< P>我肯定会使用4的可选参数特征。它摆脱了荒谬的

public void M1( string foo, string bar )
{
   // do that thang
}

public void M1( string foo )
{
  M1( foo, "bar default" ); // I have always hated this line of code specifically
}
。。。并将值放在调用方可以看到的地方

public void M1( string foo, string bar = "bar default" )
{
   // do that thang
}
更简单,更不容易出错。事实上,我认为这是过载案例中的一个错误

public void M1( string foo )
{
   M2( foo, "bar default" );  // oops!  I meant M1!
}

我还没有玩过4.0编译器,但如果我知道编译器只是为您发出重载,我不会感到震惊。

我一直在使用带有可选参数的Delphi。我改为使用重载

因为当你去创建更多的重载时,你总是会与可选的参数形式发生冲突,然后你必须将它们转换成非可选的形式


我喜欢这样一个概念,即通常有一个超级方法,其余的都是围绕这个方法的更简单的包装。

可以讨论是否应该使用可选参数或重载,但最重要的是,每个方法都有自己不可替代的领域

当与命名参数结合使用时,可选参数在与带有所有COM调用选项的长参数列表结合使用时非常有用


当方法能够对许多不同的参数类型(只是其中一个示例)进行操作时,重载是非常有用的,例如,在内部进行转换;您只需向它提供任何有意义的数据类型(某些现有重载可以接受)。用可选参数无法克服这一点。

可选参数和方法重载都有各自的优点或缺点。这取决于您的偏好,您可以在它们之间进行选择

可选参数: 仅在.Net 4.0中提供。 可选参数减少代码大小。 不能定义out和ref参数

重载方法: 您可以定义Out和ref参数。
代码大小将增加,但重载方法很容易理解。

可选参数本质上是一段元数据,用于指导正在处理方法调用的编译器在调用站点插入适当的默认值。相反,重载提供了一种方法,编译器可以通过这种方法从许多方法中选择一种,其中一些方法本身可能提供默认值。请注意,如果试图从不支持可选参数的语言编写的代码中调用指定可选参数的方法,编译器将要求指定“可选”参数,但由于在不指定可选参数的情况下调用方法等同于使用等于默认值的参数调用方法,这些语言调用这些方法没有任何障碍

在调用站点绑定可选参数的一个重要结果是,它们将根据编译器可用的目标代码版本被赋值。如果程序集
Foo
有一个默认值为5的方法
Boo(int)
,并且程序集
Bar
包含对
Foo.Boo()
的调用,编译器将把它作为
Foo.Boo(5)
进行处理。如果默认值更改为6,并且重新编译程序集
Foo
Bar
将继续调用
Foo。
decimal GetPrice(string productName, decimal discountPercentage = 0)
{

    decimal basePrice = CalculateBasePrice(productName);

    if (discountPercentage > 0)
        return basePrice * (1 - discountPercentage / 100);
    else
        return basePrice;
}
decimal GetPrice(string productName)
{
    decimal basePrice = CalculateBasePrice(productName);
    return basePrice;
}

decimal GetPrice(string productName, decimal discountPercentage)
{

    if (discountPercentage <= 0)
        throw new ArgumentException();

    decimal basePrice = GetPrice(productName);

    decimal discountedPrice = basePrice * (1 - discountPercentage / 100);

    return discountedPrice;

}
enum Match {
    Regex,
    Wildcard,
    ContainsString,
}

// Don't: This way, Enumerate() can be called in a way
//         which does not make sense:
IEnumerable<string> Enumerate(string searchPattern = null,
                              Match match = Match.Regex,
                              SearchOption searchOption = SearchOption.TopDirectoryOnly);

// Better: Provide only overloads which cannot be mis-used:
IEnumerable<string> Enumerate(SearchOption searchOption = SearchOption.TopDirectoryOnly);
IEnumerable<string> Enumerate(string searchPattern, Match match,
                              SearchOption searchOption = SearchOption.TopDirectoryOnly);
public string HandleError(string message, bool silent=true, bool isCritical=true)
{
  ...
}
HandleError("Disk is full", false);
public string HandleError(string message, /*bool silent=true,*/ bool isCritical=true)
{
  ...
}

...

// Some other distant code file:
HandleError("Disk is full", false);