1

I have some background in the python initializer (essentially Python object constructor syntax), and the syntax to instantiate an object in Python is as follows:

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

Why is it, in C#, I have to provide defaults in the body of the constructor method, when in python I can declare them as optional, and default values are passed in (see the __init__'s signature):

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;
    }
}

Why can't I do the following in 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; 
    }

Is it possible to have constructor syntax in C# that is similar (if not an exact duplicate) to Python's initializer syntax?

George Stocker
  • 57,289
  • 29
  • 176
  • 237
Jack_of_All_Trades
  • 10,942
  • 18
  • 58
  • 88

6 Answers6

7

This has been done using Named and Optional Arguments (C# Programming Guide)

Visual C# 2010 introduces named and optional arguments. Named arguments enable you to specify an argument for a particular parameter by associating the argument with the parameter's name rather than with the parameter's position in the parameter list. Optional arguments enable you to omit arguments for some parameters. Both techniques can be used with methods, indexers, constructors, and delegates.

The definition of a method, constructor, indexer, or delegate can specify that its parameters are required or that they are optional. Any call must provide arguments for all required parameters, but can omit arguments for optional parameters.

Each optional parameter has a default value as part of its definition. If no argument is sent for that parameter, the default value is used.

Adriaan Stander
  • 162,879
  • 31
  • 289
  • 284
5

You should look into Constructor Chaining. Basically boils down to constructors calling other constructors to avoid duplicate code.

Community
  • 1
  • 1
basher
  • 2,381
  • 1
  • 23
  • 34
  • This would be the best option pre-C# 4.0 – crashmstr Aug 19 '13 at 19:37
  • @crashmstr Ah, didn't know about the named and optional arguments in C#. I don't typically use C# but constructor chaining is language agnostic and reading OP's code duplication hurt my insides. Optional arguments are definitely the way to go. – basher Aug 19 '13 at 20:24
3

I program in C# and Python, so here's a view from someone who recently went from C# to Python:

C# provides a default constructor if you do not create one.

So, by default (if you didn't have a constructor already), you could instantiate the object with its defaults like follows:

var Account = new Account();

This would instantiate those properties with their respective default values.

If you provide a constructor, you must then provide the default constructor as well (if you intend on constructing an object just by: var account = new Account();:

public Account() {} //default constructor

public Account(string name)
{
    Name = name;
}

The other primitive types in your class are initialized according to their default values.

If you'd like something Pythonic, you need to be sure you're using C# 4.0; we call them Optional Parameters. Their usage (in your case) would be exactly as you wrote it:

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; 
}

A few style comments:

  • In C#, we use properties. They aren't used quite the same way in Python, and in Python you'd be more likely to use fields. Our properties are PascalCased.

  • We don't use 'in' and 'out' parameters as part of the parameter name (there's no need to, we have ref and out for when we need to pass references -- sadly something that is missing from Python (although not really sad because it makes code more complex)).

  • In C#, fields are Camel cased -- or camelCased, as it were. In Python, they'd follow Unix conventions: first_name as opposed to firstName.

  • In C#, your properties are public by default, and they should be. In Python, everyone assumes public, private is only assumed if an underscore precedes the variable -- not so in C#.

George Stocker
  • 57,289
  • 29
  • 176
  • 237
  • 2
    @crashmstr If you intend to use the default constructor's offerings, you must provide a default constructor if you have multiple constructors. If you have no constructors, the default is provided for you, and can be safely removed from your code with no issue. – George Stocker Aug 19 '13 at 19:31
  • I could be wrong -- I'm not saying I'm not -- I'm just going off of memory. I moved from programming in C# full time to Python full time about 8 months ago, so it's entirely possible that I've forgotten something. I do know that NHibernate will require a default constructor if you've provided another constructor. If I had my .NET Dev platform up right now I'd test my theory. – George Stocker Aug 19 '13 at 19:33
  • I'm looking at a class that has two constructors, both with arguments, and no constructor with no parameters defined. So how is that "must"? Of course, this might prevent code from working that requires a default constructor in a class. – crashmstr Aug 19 '13 at 19:35
  • 2
    Perhaps not so much a "must" as a "won't generate one for you". – Bart Aug 19 '13 at 19:35
  • @crashmstr What happens when you instantiate an object of that class without any parameters? – George Stocker Aug 19 '13 at 19:36
  • Can't. There is no default constructor like @Bart says. Sometimes, that is the whole point. You need to build the object with the required parameters, or not at all. – crashmstr Aug 19 '13 at 19:38
  • 1
    @GeorgeStocker I think the distinction he's getting at is that the compiler won't complain if you never use it without any parameters. If it would, then it would be a "must". – Bart Aug 19 '13 at 19:39
  • @Bart That makes sense. I've updated my comment to reflect a more accurate state of affairs: If you intend on using the default constructor to instantiate an object of a class, you have to provide it if you have multiple constructors. – George Stocker Aug 19 '13 at 19:40
0

If you want a more short hand approach you can use the object initializer.

public class Account
{
   public string Name { get; set; } 
   public string Address { get; set; } 
   public decimal Balance { get; set; } 
}

var account = new Account { Name = "Dave" };
Dave Hillier
  • 18,105
  • 9
  • 43
  • 87
0

As of VS2010 (I believe C# 4.0) C# does allow named and optional parameters similar to how you use them in Python.

Unfortunately, older versions of C# don't have this (I think somewhat due to C#'s Java legacy, but this is just speculation on my part).

helloworld922
  • 10,801
  • 5
  • 48
  • 85
0

C# allows you also to utilize object initializers:

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 }

You can that way specify dynamically which fields you want to initialize.

Przemysław Kalita
  • 1,977
  • 3
  • 18
  • 28