4
\$\begingroup\$

I'm trying to tidy the following fragment of code:

        if (this.Details.Recipients.Count > 0)
            this.Recipient = this.Details.Recipients[0];
        else
        {
            this.Recipient = new Contact();
            this.Details.Recipients.Add(this.Recipient);
        }
        if (this.Details.CCs.Count > 0)
            this.CC = this.Details.CCs[0];
        else
        {
            this.CC = new Contact();
            this.Details.CCs.Add(this.CC);
        }
        if (this.Details.BCCs.Count > 0)
            this.BCC = this.Details.BCCs[0];
        else
        {
            this.BCC = new Contact();
            this.Details.BCCs.Add(this.BCC);
        }

But when I simplify it in the following way, I run into problems because I have to pass the objects by ref. And if I do that, then I get an error (A property, indexer or dynamic member access may not be passed as an out or ref):

        InitialiseContacts(this.Details.Recipients, this.Recipient);
        InitialiseContacts(this.Details.CCs, this.CC);
        InitialiseContacts(this.Details.BCCs, this.BCC);
    }

    static void InitialiseContacts(ObservableCollection<Contact> contacts, Contact contact)
    {
        if (contacts.Count > 0)
            contact = contacts[0];
        else
        {
            contact = new Contact();
            contacts.Add(contact);
        }
    }

Any ideas?

\$\endgroup\$
6
\$\begingroup\$

So I think the error you is getting is hopefully obvious. You can't pass a property by ref. There is quite a few answers if you google this. Here's a quick one I found on stack overflow

So instead don't pass in the object, but rather have a new instance returned from the method. Something along the lines of

this.BCC = FirstOrCreateIfEmpty(this.Details.BCCs);
this.CC = FirstOrCreateIfEmpty(this.Details.CCs);

public Contact FirstOrCreateIfEmpty(List<Contact> contacts)
{
    if(contacts.Any())
    {
        return contacts.First();
    } 

    var contact = new Contact();
    contacts.Add(contact);

    return contact; 
} 
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ There are ways to pass a property by reference if you really need to of course, but in an overly accurate sense. You can pass delegates that assign or get from the property. Still, you're probably right in not suggesting that. \$\endgroup\$ – Magus Mar 6 '14 at 18:52
  • \$\begingroup\$ @Magnus Yes, those examples are shown in the Stack overflow link. However, that is still not passing a property by reference as such I believe. Just a work around to effect the same result. \$\endgroup\$ – dreza Mar 6 '14 at 19:04
  • \$\begingroup\$ Technically, a property is a hidden pair of methods, so delegates are somewhat closer. You can pass the getter and setter directly with reflection, but that's even more horrific. But again, you've suggested a solution which has no need for either, which is definitely preferable. \$\endgroup\$ – Magus Mar 6 '14 at 19:11
  • \$\begingroup\$ Thanks. Yes, i see now how I could use a delegate if i had to. But I don't and your solution is nice and easy to understand/read. \$\endgroup\$ – Matt Fitzmaurice Mar 7 '14 at 9:12
  • \$\begingroup\$ Thanks, I ended up creating an extension method to help me: public static T FirstOrCreateIfEmpty<T>(this IList<T> list) where T : new() { if (list.Any()) return list.First(); var item = new T(); list.Add(item); return item; } \$\endgroup\$ – Matt Fitzmaurice Mar 9 '14 at 1:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.