【问题标题】:How do I make the C# constructor syntax more pythonic?如何使 C# 构造函数语法更 Pythonic?
【发布时间】:2013-08-21 16:44:01
【问题描述】:

我对python初始化器(本质上是Python对象构造器语法)有一定的了解,在Python中实例化一个对象的语法如下:

class Account:
     def __init__(self,name=None,address="Not Supplied",balance=0.0):
         this.name = name
         this.address=address
         this.balance=balance

为什么呢,在 C# 中,我必须在构造方法的主体中提供默认值,而在 python 中我可以将它们声明为可选,并传入默认值(参见__init__ 的签名):

public class Account
{
    private string name; 
    private string address;
    private decimal balance;

    public Account (string inName, string inAddress, decimal inBalance)
    { 
        name = inName; 
        address = inAddress; 
        balance = inBalance; 
    }

    public Account (string inName, string inAddress) 
    {
        name = inName; 
        address = inAddress;
        balance = 0;
    } 

    public Account (string inName) 
    { 
        name = inName;
        address = "Not Supplied";
        balance = 0;
    }
}

为什么我不能在 C# 中执行以下操作?

public class Account
{
    private string name; 
    private string address;
    private decimal balance;

    public Account (string inName, string inAddress="not supplied", decimal inBalance=0;)
    { 
        name = inName; 
        address = inAddress; 
        balance = inBalance; 
    }

C# 中的构造函数语法是否可能与 Python 的初始化器语法相似(如果不是完全重复的话)?

【问题讨论】:

  • 我不确定问题是什么。。第二个 C# sn-p 应该与您的 python sn-p 匹配(忽略分号)。
  • 我不明白...最后一个 sn-p 你希望它如何工作?因为它确实是这样工作的。
  • @default.kramer:最后一个 sn-p 是我期望它工作的方式。是这样的吗?
  • 是的,从 C# 4.0 开始
  • 你试过了吗? (答案是肯定的)

标签: c# python constructor default-constructor object-initialization


【解决方案1】:

这是使用Named and Optional Arguments (C# Programming Guide)完成的

Visual C# 2010 引入了命名参数和可选参数。命名 arguments 使您能够为特定参数指定参数 通过将参数与参数名称相关联,而不是与 参数在参数列表中的位置。 可选参数 使您可以省略某些参数的参数。 这两种技术 可以与方法、索引器、构造函数和委托一起使用。

方法、构造函数、索引器或委托的定义可以 指定其参数是必需的还是可选的。 任何调用都必须为所有必需的参数提供参数,但可以 省略可选参数的参数。

每个可选参数都有一个默认值作为其定义的一部分。 如果没有为该参数发送参数,则使用默认值。

【讨论】:

    【解决方案2】:

    您应该查看Constructor Chaining。基本上归结为构造函数调用其他构造函数以避免重复代码。

    【讨论】:

    • 这将是 C# 4.0 之前的最佳选择
    • @crashmstr 啊,不知道 C# 中的命名参数和可选参数。我通常不使用 C#,但构造函数链接与语言无关,阅读 OP 的代码重复会伤害我的内心。可选参数绝对是要走的路。
    【解决方案3】:

    我用 C# 和 Python 编程,所以这是最近从 C# 转到 Python 的人的观点:

    如果您不创建,C# 会提供默认构造函数。

    因此,默认情况下(如果您还没有构造函数),您可以使用其默认值实例化对象,如下所示:

    var Account = new Account();
    

    这将使用它们各自的默认值实例化这些属性。

    如果您提供构造函数,则还必须提供默认构造函数(如果您打算通过以下方式构造对象:var account = new Account();:

    public Account() {} //default constructor
    
    public Account(string name)
    {
        Name = name;
    }
    

    您的类中的其他原始类型根据它们的默认值进行初始化。

    如果您喜欢 Pythonic,您需要确保您使用的是 C# 4.0; we call them Optional Parameters。它们的用法(在您的情况下)将与您所写的完全相同:

    public string Name { get; set;} 
    public string Address {get; set;}
    public decimal Balance {get; set;}
    
    public Account (string name, string address="not supplied", decimal balance=0;)
    { 
        Name = name; 
        Address = address; 
        Balance = balance; 
    }
    

    一些风格的cmets:

    • 在 C# 中,我们使用属性。它们在 Python 中的使用方式并不完全相同,在 Python 中,您更有可能使用字段。我们的属性是 PascalCased。

    • 我们不使用 'in' 和 'out' 参数作为参数名称的一部分(没有必要,我们有 refout 用于当我们需要传递引用时——可悲的是Python 中缺少的一些东西(虽然并不难过,因为它使代码更复杂))。

    • 在 C# 中,字段是 Camel 大小写的 - 或 camelCased,实际上。在 Python 中,它们遵循 Unix 约定:first_name 而不是 firstName。

    • 在 C# 中,您的属性默认为 public,它们应该是。在 Python 中,每个人都假定 publicprivate 仅在变量前面有下划线时才被假定——在 C# 中不是这样。

    【讨论】:

    • @crashmstr 如果您打算使用默认构造函数,如果您有多个构造函数,则必须提供默认构造函数。如果您没有构造函数,则为您提供默认值,并且可以安全地从代码中删除。
    • 我可能是错的——我不是说我不是——我只是失忆了。大约 8 个月前,我从全职 C# 编程转到全职 Python,所以我完全有可能忘记了一些东西。我知道如果您提供了另一个构造函数,NHibernate 将需要一个默认构造函数。如果我现在有我的 .NET 开发平台,我会测试我的理论。
    • 我正在查看一个有两个构造函数的类,两个构造函数都带有参数,并且没有定义参数的构造函数。那么“必须”如何?当然,这可能会阻止需要在类中使用默认构造函数的代码。
    • 也许与其说是“必须”,不如说是“不会为您生成”。
    • @GeorgeStocker 我认为他得到的区别是,如果你从不使用它而不使用任何参数,编译器就不会抱怨。如果可以,那将是“必须”。
    【解决方案4】:

    如果您想要更简洁的方法,您可以使用对象初始化器。

    public class Account
    {
       public string Name { get; set; } 
       public string Address { get; set; } 
       public decimal Balance { get; set; } 
    }
    
    var account = new Account { Name = "Dave" };
    

    【讨论】:

      【解决方案5】:

      截至 VS2010(我相信 C# 4.0)C# 确实允许 named and optional parameters 类似于您在 Python 中使用它们的方式。

      不幸的是,旧版本的 C# 没有这个(我认为这在某种程度上是由于 C# 的 Java 遗留问题,但这只是我的猜测)。

      【讨论】:

        【解决方案6】:

        C# 还允许您使用对象初始化器:

        public class Account
        {
            public string name { get; set;} 
            public string address { get; set;} 
            public decimal balance { get; set;} 
        }
        
        Account acc = new Account () { name="Some Name", address="Some Address", balance=10.0 }
        

        您可以通过这种方式动态指定要初始化的字段。

        【讨论】:

          猜你喜欢
          • 2023-04-09
          • 2015-12-01
          • 1970-01-01
          • 2014-07-05
          • 2019-04-14
          • 2017-11-29
          • 1970-01-01
          • 2017-07-30
          • 2016-07-08
          相关资源
          最近更新 更多