Friday, July 22, 2011

How to return private collection


Did you ever try returning a private array like following?


    public class TestPrivateArrays
    {
        private string[] names;
 
        public string[] Names { 
            get
            {
                return names;
            } 
        }
}
            //initialize collection in constructor
            names = new string[] { "Abhishek""Tiwari" };


And you thought, no one from the external world can modify it? Wrong. Since client still has direct reference of each items of collection/Array, he has full liberty to modify it.


     TestPrivateArrays tpa = new TestPrivateArrays();
     tpa.Names[0] = "Modified"//my private array gets modified here


So question is whether you can stop your client modifying your array. Answer is yes, you just need to know how to return your collection items as readonly.

1. Return clone of Array


    public class TestPrivateArrays
    {
        private string[] names;
 
        public string[] Names { 
            get
            {
                return (string[])names.Clone();
            } 
        }
}


You can see, even if client tries to modify the array item, he won't be able to do so. since he is actually modifying a copy of that array but whenever he tries to get the array item, he will get the original one i.e. the unmodified one.



2. Return readonly collection


If you are using .NET generics for e.g. list. You can return the collection as readonly in the following manner.


        private List<string> listNames;
 
        public IList<string> ListNames
        {
            get
            {
                return listNames.AsReadOnly();
            }
        }
            //initialize collection in constructor
            listNames = new List<string> { "Abhishek""Tiwari" };


Now if user tries to modify the collection, he will get a runtime error saying that collection is readonly (see following).



3. Use some inbuilt readonly collection


you can find a datastructure called ReadOnlyCollection under System.Collections.ObjectModel which is strong typed and templatized. You can use that in following manner.


        private System.Collections.ObjectModel.ReadOnlyCollection<string> colNames;
        public System.Collections.ObjectModel.ReadOnlyCollection<string> ColNames
        {
            get
            {
                return colNames;
            }
        }
            //initialize collection in constructor
            colNames = new System.Collections.ObjectModel.ReadOnlyCollection<string>(new List<string> { "Abhishek""Tiwari" });


Note that if user tries to modify this collection, he will get compile time error (remember in case of list, it was runtime error because when you modify the list, it evaluates its isReadOnly property at runtime).

Thanks for reading the post.

No comments:

Post a Comment