The following program will fail because Contracts is not instantiated.
Of course I can instantiate it in my constructor but if I have dozens of properties and/or multiple constructors I have to keep track of which are instantiated, etc.
And of course I could create large blocks for these properties with full gets and sets and private field variables, etc. But this gets messy as well.
Isn't there a way to automatically instantiate these collections with the nice C# property syntax?
using System;
using System.Collections.Generic;
namespace TestProperty232
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer();
customer.FirstName = "Jim";
customer.LastName = "Smith";
Contract contract = new Contract();
contract.Title = "First Contract";
customer.Contracts.Add(contract);
开发者_Go百科 Console.ReadLine();
}
}
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Contract> Contracts { get; set; }
public Customer()
{
//Contracts = new List<Contract>();
}
}
public class Contract
{
public string Title { get; set; }
}
}
There is no such syntactic sugar, but I'd like to point out a few things:
- Collection properties should be read-only in any case.
- If you have a lot of such properties in a single type, it's a strong symptom that you are violating the Single Responsibility Principle
- If you have multiple constructors, you should always take great care that there's only one constructor that does the real work, and all other constructors delegate to that constructor. Alternatively you can delegate all constructor work to a private Initialize method.
No, there is no sugar. Instantiate them in your parameterless constructor and redirect all your other constructors there, so that it will always execute.
class MyClass
{
//Many properties
public MyClass()
{
//Initialize here
}
public MyClass(string str) : this()
{
//do other stuff here
}
}
Long answer: how's this?
using System.Collections.Generic;
namespace proto
{
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Contract
{
public List<Customer> Customers { get; set; }
public string Title { get; set; }
}
public class ContractDemo
{
public Contract CreateDemoContract()
{
Contract newContract = new Contract
{
Title = "Contract Title",
Customers = new List<Customer>
{
new Customer
{
FirstName = "First Name",
LastName = "Last Name"
},
new Customer
{
FirstName = "Other",
LastName = "Customer"
}
}
};
return newContract;
}
}
}
Sugary or lemony : you decide : (VS 2010 beta 2, FrameWork 4)
Customer customer = new Customer
{
FirstName = "Jim",
LastName = "Smith",
Contracts = new List<Contract> { new Contract { Title ="First Contract" } }
};
Works fine with your existing class definitions, but feels awkward to read ?
best,
The short answer is no.
Not sure what you are actually looking for, but you could tidy it up a bit like this...
using System;
using System.Collections.Generic;
namespace TestProperty232
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer() {
FirstName = "Jim",
LastName = "Smith"
};
Contract contract = new Contract() {
Title = "First Contract"
};
customer.Contracts = new List<Contract>() { contract };
Console.ReadLine();
}
}
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Contract> Contracts { get; set; }
public Customer()
{
//Contracts = new List<Contract>();
}
}
public class Contract
{
public string Title { get; set; }
}
}
You could make Contracts not be an autoproperty:
private List<Contract> _contracts;
public List<Contract> Contracts
{
get
{
if (_contracts == null)
{
_contracts = new List<Contract>();
}
return _contracts;
}
set
{
if (!_contracts.Equals(value))
{
_contracts = value;
}
}
}
That will allow you not to have to explicitly instantiate Contracts.
精彩评论