0

When creating objects like:

var customers = new Customers
{
    Persons = new List<Person>
    {
        new Person { CustomId = "111" },
        new Person { CustomId = "222" }
    },
    Organizations = new List<Organization>
    {
        new Organization { CustomId = "333" }
    },
    Keys = new HashSet<string> { "111", "222", "333" }
};

I want to change the initialization of Keys to use the previous value from Person[0].CustomId, Person[1].CustomId and Organization[0].CustomId. (Not hardcoded like this "111", "222", "333")

Is there a simple way to do this inside this type of initialization? I can add the keys after the initialization of customers like this:

foreach (var person in customers.Persons)
{
    customers.Keys.Add(person.CustomId);
}
foreach (var org in customers.Organizations)
{
    customers.Keys.Add(org.CustomId);
}

But I cannot create Keys from Person and Organization properties in the same initialization as customers?

ken1nil
  • 915
  • 3
  • 9
  • 21
  • You can do that inside object initializer afaik – Vsevolod Goloviznin Jan 12 '15 at 15:31
  • 2
    Perhaps `Customers` should infer the keys based on the properties? Why would you explicitly do it anyway? – Jon Skeet Jan 12 '15 at 15:31
  • 2
    This should really be something done in the `Customer` constructor if this is how all customers are constructed. – Servy Jan 12 '15 at 15:34
  • Why 'someone' set Keys explicitly is to be able to do a search in customers based on CustomId, Persons and Organizations can have the same CustomId, it is not unique. And to use operations like .Distinct() .Count on the Key instead of searching two collections(Persons, Organizations) for Count – ken1nil Jan 12 '15 at 16:22

2 Answers2

5

No, you can't do that.

You can create the collections first, and concatenate the selected keys:

var persons = new List<Person>
{
    new Person { CustomId = "111" },
    new Person { CustomId = "222" }
};

var organizations = new List<Organization>
{
    new Organization { CustomId = "333" }
};

var keys = persons.Select(p => p.CustomId)
                  .Concat(organizations.Select(o => o.CustomId));

var customers = new Customers
{
    Persons = persons,
    Organizations = organizations,
    Keys = new HashSet<string>(keys),
}

But like others said, there's more issues with this implementation. Do you want to use this syntax for every consumer of the Customers class? How will you keep the key collection up to date with the Persons and Organizations collections, like when you add or remove items from them?

public class Customers
{
    public List<Person> Persons { get; set; }
    public List<Organization> Organizations { get; set; }

    public Customers()
    {
        Persons = new List<Person>();
        Organizations = new List<Organization>();
    }

    public Customers(IEnumerable<Person> persons,
                     IEnumerable<Organization> organizations)
        : this()
    {
        Persons.AddRange(persons);
        Organizations.AddRange(organizations);
    }

    public IEnumerable<string> Keys
    {
        return Persons.Select(p => p.CustomId)
                      .Concat(Organizations.Select(o => o.CustomId));
    }
}

Then a call site may look like this:

var persons = new List<Person>
{
    new Person { CustomId = "111" },
    new Person { CustomId = "222" }
};

var organizations = new List<Organization>
{
    new Organization { CustomId = "333" }
};

var customers = new Customers(persons, organizations);
var keys = customers.Keys;
Community
  • 1
  • 1
CodeCaster
  • 147,647
  • 23
  • 218
  • 272
  • may be it's a way to go but how he can add keys and retrieve them at runtime ?? – BRAHIM Kamel Jan 12 '15 at 15:37
  • ok so Key cannot be a property I think you should use SetKeys(key as argument ) and GetKeys() which concat the two lists – BRAHIM Kamel Jan 12 '15 at 15:40
  • @Kamel not sure what you mean. OP has defined a `Customers` class with a `Keys` property, which is a valid identifier. I did not change the class definition. – CodeCaster Jan 12 '15 at 15:41
  • Yes, the call part where you have var keys = customers.Keys; is now handled "automaticly" when adding Persons/Organizations. So the short answer is you cannot call Person[0].CustomId inside the first creation!? – ken1nil Jan 12 '15 at 16:01
  • 1
    @Niike2 that's correct, you cannot refer to other properties of the object you are initializing in an object initializer. – CodeCaster Jan 12 '15 at 16:02
0

Make Keys into a public property like:

public HashSet<string> Keys
{
   get
   {
      // create and return a new hashset from persons and organizations
   }    
}

This way you newer have to think about updating your Keys member.

Servy
  • 202,030
  • 26
  • 332
  • 449
jrb
  • 1,708
  • 2
  • 13
  • 20