PC Review


Reply
Thread Tools Rate Thread

Best Practise: Returning private List<> as a Property

 
 
Paul
Guest
Posts: n/a
 
      16th Jan 2007
Hi,

I feel I'm going around circles on this one and would appreciate some other
points of view.

From a design / encapsulation point of view, what's the best practise for
returning a private List<> as a property.

Consider the example below, the class "ListTest" contains a private "List<>"
called "strings" - it also provides a public method to add to that list,
this method could contain all sorts of validation / modification of the
string to be added (encapsulation). However by then exposing the private
List<> as a public property you give the end user of your class the ability
to add to your List<> as show below.

I understand why the above happens, I'm just trying to think what the best
course of action is if you always want your user to use the function to add
to your list, whilst retaining a property to access the list? List<>
doesn't contain a clone method - you could create this I know, but then the
amount of processing that involves implies it should be a method rather than
a parameter (parameters shouldn't really consider processor intensive code).

Like I say, I feel I'm going around in circles on this one, even to the
point of wondering if it actually matters.

Regards,

- Paul.
====================================
using System;
using System.Collections.Generic;
using System.Text;

class Program
{
static void Main(string[] args)
{
ListTest listTest = new ListTest();
listTest.AddString("Test 1"); // << Add the string the correct way.
Console.WriteLine(listTest.Strings.Count);
listTest.Strings.Add("Test 2"); // << by-pass the AddString()
function.
Console.WriteLine(listTest.Strings.Count);
}
}

class ListTest
{
private List<string> strings = null;

public void AddString(string stringToAdd)
{
if (strings == null)
strings = new List<string>();
strings.Add(stringToAdd);
}
public List<string> Strings { get { return this.strings; } }
}
====================================
Output is:
1
2


 
Reply With Quote
 
 
 
 
Giulio Petrucci
Guest
Posts: n/a
 
      16th Jan 2007
Hi Paul,

Paul ha scritto:
[cut]

I think I haven't properly got what you need...
Antyway - taking a look to your code - the best way should be you to
create your *own* collection (implementing ICollection<T>) and
customizing the "Add" method.

HTH,
Giulio
 
Reply With Quote
 
Dustin Campbell
Guest
Posts: n/a
 
      16th Jan 2007
> I feel I'm going around circles on this one and would appreciate some
> other points of view.
>
> From a design / encapsulation point of view, what's the best practise
> for returning a private List<> as a property.
>
> Consider the example below, the class "ListTest" contains a private
> "List<>" called "strings" - it also provides a public method to add to
> that list, this method could contain all sorts of validation /
> modification of the string to be added (encapsulation). However by
> then exposing the private List<> as a public property you give the end
> user of your class the ability to add to your List<> as show below.
>
> I understand why the above happens, I'm just trying to think what the
> best course of action is if you always want your user to use the
> function to add to your list, whilst retaining a property to access
> the list? List<> doesn't contain a clone method - you could create
> this I know, but then the amount of processing that involves implies
> it should be a method rather than a parameter (parameters shouldn't
> really consider processor intensive code).
>
> Like I say, I feel I'm going around in circles on this one, even to
> the point of wondering if it actually matters.
>
> ====================================
> using System;
> using System.Collections.Generic;
> using System.Text;
> class Program
> {
> static void Main(string[] args)
> {
> ListTest listTest = new ListTest();
> listTest.AddString("Test 1"); // << Add the string the correct
> way.
> Console.WriteLine(listTest.Strings.Count);
> listTest.Strings.Add("Test 2"); // << by-pass the AddString()
> function.
> Console.WriteLine(listTest.Strings.Count);
> }
> }
> class ListTest
> {
> private List<string> strings = null;
> public void AddString(string stringToAdd)
> {
> if (strings == null)
> strings = new List<string>();
> strings.Add(stringToAdd);
> }
> public List<string> Strings { get { return this.strings; } }
> }
> ====================================
> Output is:
> 1
> 2


List<> should be used internally and never exposed. Once you expose it, you're
design is locked into using it. If you just need a way to iterate over the
List<> from outside, you might consider making ListTest implement IEnumerable<string>
like this:

class ListTest: IEnumerable<string>
{
List<string> strings = new List<string>();

public IEnumerator<string> GetEnumerator()
{
return strings.GetEnumerator();
}
}

Or, if you want to return the contents, you could expose a read-only indexer:

class ListTest
{
List<string> strings = new List<string>();

public string this[int index] { get { return strings[index]; } }
}

Another option is to return a ReadOnlyCollection<string>:

class ListTest
{
List<string> strings = new List<string>();

public ReadOnlyCollection<string> Strings { get { return strings.AsReadOnly();
} }
}

You might even consider doing all three. But, directly exposing the inner
bits of your class is a bad idea for lots of reasons.

Best Regards,
Dustin Campbell
Developer Express Inc.


 
Reply With Quote
 
Giulio Petrucci
Guest
Posts: n/a
 
      16th Jan 2007
Dustin Campbell ha scritto:
> List<> should be used internally and never exposed. Once you expose it,
> you're design is locked into using it. If you just need a way to iterate
> over the List<> from outside, you might consider making ListTest
> implement IEnumerable<string> like this:


....and if you need to "manipulate" object from outside
(add/remove/clear) you should use a ICollection<T>.

My 2 cents,
Giulio - Italia

--
OnAir: Metallica - the frayed ends of sanity
 
Reply With Quote
 
Christof Nordiek
Guest
Posts: n/a
 
      16th Jan 2007
Hi,

you could use the AsReadOnly method of the List<T> class. It returns a
writeprotected wrapper around your list.

your Strings property would look like this:

public ReadOnlyCollection<string> Strings { get { return
strings.AsReadOnly() } }

The returned List will still have the Add method soice it implements IList<>
and List<>, but they will cause exceptions.
Not very nice, but atleast the caller can't change your internals.

Christof

"Paul" <(E-Mail Removed)> schrieb im Newsbeitrag
news:(E-Mail Removed)...
> Hi,
>
> I feel I'm going around circles on this one and would appreciate some
> other points of view.
>
> From a design / encapsulation point of view, what's the best practise for
> returning a private List<> as a property.
>
> Consider the example below, the class "ListTest" contains a private
> "List<>" called "strings" - it also provides a public method to add to
> that list, this method could contain all sorts of validation /
> modification of the string to be added (encapsulation). However by then
> exposing the private List<> as a public property you give the end user of
> your class the ability to add to your List<> as show below.
>
> I understand why the above happens, I'm just trying to think what the best
> course of action is if you always want your user to use the function to
> add to your list, whilst retaining a property to access the list? List<>
> doesn't contain a clone method - you could create this I know, but then
> the amount of processing that involves implies it should be a method
> rather than a parameter (parameters shouldn't really consider processor
> intensive code).
>
> Like I say, I feel I'm going around in circles on this one, even to the
> point of wondering if it actually matters.
>
> Regards,
>
> - Paul.
> ====================================
> using System;
> using System.Collections.Generic;
> using System.Text;
>
> class Program
> {
> static void Main(string[] args)
> {
> ListTest listTest = new ListTest();
> listTest.AddString("Test 1"); // << Add the string the correct way.
> Console.WriteLine(listTest.Strings.Count);
> listTest.Strings.Add("Test 2"); // << by-pass the AddString()
> function.
> Console.WriteLine(listTest.Strings.Count);
> }
> }
>
> class ListTest
> {
> private List<string> strings = null;
>
> public void AddString(string stringToAdd)
> {
> if (strings == null)
> strings = new List<string>();
> strings.Add(stringToAdd);
> }
> public List<string> Strings { get { return this.strings; } }
> }
> ====================================
> Output is:
> 1
> 2
>



 
Reply With Quote
 
JS
Guest
Posts: n/a
 
      16th Jan 2007
> ...and if you need to "manipulate" object from outside
> (add/remove/clear) you should use a ICollection<T>.


I'm just curious. Why is returning an ICollection<T> preferrable to
returning an IList<T> ?

 
Reply With Quote
 
Bruce Wood
Guest
Posts: n/a
 
      17th Jan 2007

Paul wrote:
> Hi,
>
> I feel I'm going around circles on this one and would appreciate some other
> points of view.
>
> From a design / encapsulation point of view, what's the best practise for
> returning a private List<> as a property.
>
> Consider the example below, the class "ListTest" contains a private "List<>"
> called "strings" - it also provides a public method to add to that list,
> this method could contain all sorts of validation / modification of the
> string to be added (encapsulation). However by then exposing the private
> List<> as a public property you give the end user of your class the ability
> to add to your List<> as show below.
>
> I understand why the above happens, I'm just trying to think what the best
> course of action is if you always want your user to use the function to add
> to your list, whilst retaining a property to access the list? List<>
> doesn't contain a clone method - you could create this I know, but then the
> amount of processing that involves implies it should be a method rather than
> a parameter (parameters shouldn't really consider processor intensive code).
>
> Like I say, I feel I'm going around in circles on this one, even to the
> point of wondering if it actually matters.
>
> Regards,
>
> - Paul.
> ====================================
> using System;
> using System.Collections.Generic;
> using System.Text;
>
> class Program
> {
> static void Main(string[] args)
> {
> ListTest listTest = new ListTest();
> listTest.AddString("Test 1"); // << Add the string the correct way.
> Console.WriteLine(listTest.Strings.Count);
> listTest.Strings.Add("Test 2"); // << by-pass the AddString()
> function.
> Console.WriteLine(listTest.Strings.Count);
> }
> }
>
> class ListTest
> {
> private List<string> strings = null;
>
> public void AddString(string stringToAdd)
> {
> if (strings == null)
> strings = new List<string>();
> strings.Add(stringToAdd);
> }
> public List<string> Strings { get { return this.strings; } }
> }
> ====================================
> Output is:
> 1
> 2


You might choose to use a custom list type. Take a look at how
ListViewItemCollection works.

 
Reply With Quote
 
Giulio Petrucci
Guest
Posts: n/a
 
      17th Jan 2007
Hi JS,

JS ha scritto:
> I'm just curious. Why is returning an ICollection<T> preferrable to
> returning an IList<T> ?


It's just a more "restricted" interface.

Kind regards,
Giulio
 
Reply With Quote
 
Paul Hadfield
Guest
Posts: n/a
 
      17th Jan 2007
Christof,

Thanks for the advice, it's a very clean solution - nice to know that I
wasn't going mad thinking there was a better way of doing things.

Also, you have to cast the returned "ReadOnlyCollection" property as a
"ICollection<T>" to get the Add value because it's an Explicit Interface
implementation (see below) - if you just use the property without the cast
you can't even see / use the Add method.

((ICollection<String>)listTest.Strings).Add("Test 2"); // << This will throw
the exception.

Thanks again,

- Paul.

"Christof Nordiek" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Hi,
>
> you could use the AsReadOnly method of the List<T> class. It returns a
> writeprotected wrapper around your list.
>
> your Strings property would look like this:
>
> public ReadOnlyCollection<string> Strings { get { return
> strings.AsReadOnly() } }
>
> The returned List will still have the Add method soice it implements
> IList<> and List<>, but they will cause exceptions.
> Not very nice, but atleast the caller can't change your internals.
>
> Christof
>
> "Paul" <(E-Mail Removed)> schrieb im Newsbeitrag
> news:(E-Mail Removed)...
>> Hi,
>>
>> I feel I'm going around circles on this one and would appreciate some
>> other points of view.
>>
>> From a design / encapsulation point of view, what's the best practise for
>> returning a private List<> as a property.
>>
>> Consider the example below, the class "ListTest" contains a private
>> "List<>" called "strings" - it also provides a public method to add to
>> that list, this method could contain all sorts of validation /
>> modification of the string to be added (encapsulation). However by then
>> exposing the private List<> as a public property you give the end user of
>> your class the ability to add to your List<> as show below.
>>
>> I understand why the above happens, I'm just trying to think what the
>> best course of action is if you always want your user to use the function
>> to add to your list, whilst retaining a property to access the list?
>> List<> doesn't contain a clone method - you could create this I know, but
>> then the amount of processing that involves implies it should be a method
>> rather than a parameter (parameters shouldn't really consider processor
>> intensive code).
>>
>> Like I say, I feel I'm going around in circles on this one, even to the
>> point of wondering if it actually matters.
>>
>> Regards,
>>
>> - Paul.
>> ====================================
>> using System;
>> using System.Collections.Generic;
>> using System.Text;
>>
>> class Program
>> {
>> static void Main(string[] args)
>> {
>> ListTest listTest = new ListTest();
>> listTest.AddString("Test 1"); // << Add the string the correct
>> way.
>> Console.WriteLine(listTest.Strings.Count);
>> listTest.Strings.Add("Test 2"); // << by-pass the AddString()
>> function.
>> Console.WriteLine(listTest.Strings.Count);
>> }
>> }
>>
>> class ListTest
>> {
>> private List<string> strings = null;
>>
>> public void AddString(string stringToAdd)
>> {
>> if (strings == null)
>> strings = new List<string>();
>> strings.Add(stringToAdd);
>> }
>> public List<string> Strings { get { return this.strings; } }
>> }
>> ====================================
>> Output is:
>> 1
>> 2
>>

>
>



 
Reply With Quote
 
Paul Hadfield
Guest
Posts: n/a
 
      17th Jan 2007
Thanks Dustin,

That's really helpful - I've gone with the ReadOnlyCollection option as it
does exactly what I wanted - sometimes I do want to return the whole
collection, not just iterate over it or return specific elements.

Regards,

- Paul.


"Dustin Campbell" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
>> I feel I'm going around circles on this one and would appreciate some
>> other points of view.
>>
>> From a design / encapsulation point of view, what's the best practise
>> for returning a private List<> as a property.
>>
>> Consider the example below, the class "ListTest" contains a private
>> "List<>" called "strings" - it also provides a public method to add to
>> that list, this method could contain all sorts of validation /
>> modification of the string to be added (encapsulation). However by
>> then exposing the private List<> as a public property you give the end
>> user of your class the ability to add to your List<> as show below.
>>
>> I understand why the above happens, I'm just trying to think what the
>> best course of action is if you always want your user to use the
>> function to add to your list, whilst retaining a property to access
>> the list? List<> doesn't contain a clone method - you could create
>> this I know, but then the amount of processing that involves implies
>> it should be a method rather than a parameter (parameters shouldn't
>> really consider processor intensive code).
>>
>> Like I say, I feel I'm going around in circles on this one, even to
>> the point of wondering if it actually matters.
>>
>> ====================================
>> using System;
>> using System.Collections.Generic;
>> using System.Text;
>> class Program
>> {
>> static void Main(string[] args)
>> {
>> ListTest listTest = new ListTest();
>> listTest.AddString("Test 1"); // << Add the string the correct
>> way.
>> Console.WriteLine(listTest.Strings.Count);
>> listTest.Strings.Add("Test 2"); // << by-pass the AddString()
>> function.
>> Console.WriteLine(listTest.Strings.Count);
>> }
>> }
>> class ListTest
>> {
>> private List<string> strings = null;
>> public void AddString(string stringToAdd)
>> {
>> if (strings == null)
>> strings = new List<string>();
>> strings.Add(stringToAdd);
>> }
>> public List<string> Strings { get { return this.strings; } }
>> }
>> ====================================
>> Output is:
>> 1
>> 2

>
> List<> should be used internally and never exposed. Once you expose it,
> you're design is locked into using it. If you just need a way to iterate
> over the List<> from outside, you might consider making ListTest implement
> IEnumerable<string> like this:
>
> class ListTest: IEnumerable<string>
> {
> List<string> strings = new List<string>();
>
> public IEnumerator<string> GetEnumerator()
> {
> return strings.GetEnumerator();
> }
> }
>
> Or, if you want to return the contents, you could expose a read-only
> indexer:
>
> class ListTest
> {
> List<string> strings = new List<string>();
>
> public string this[int index] { get { return strings[index]; } }
> }
>
> Another option is to return a ReadOnlyCollection<string>:
>
> class ListTest
> {
> List<string> strings = new List<string>();
>
> public ReadOnlyCollection<string> Strings { get { return
> strings.AsReadOnly(); } }
> }
>
> You might even consider doing all three. But, directly exposing the inner
> bits of your class is a bad idea for lots of reasons.
>
> Best Regards,
> Dustin Campbell
> Developer Express Inc.
>
>



 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Returning private members of base types Andrus Microsoft C# .NET 0 5th Apr 2008 05:44 PM
Overriding private interface property? Joel Microsoft C# .NET 1 11th Feb 2005 08:19 PM
Property - Public Get but Private Set Michael Moreno Microsoft C# .NET 6 31st Mar 2004 01:55 PM
public private property Sunny Microsoft C# .NET 2 4th Sep 2003 03:48 PM
private property Simon Microsoft VC .NET 2 23rd Jul 2003 08:04 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 06:43 AM.