Exposing array-like data structure using properties - c#

Its typical to expose internal data structures as properties to your business class. But when we have to expose array-like structures (like List<Rule> rules) we might encounter a problem of wrong usage (as in Option 1).
Its suggested to expose clone of such data structures as properties, so that internal structure does not get disturbed.
Does any one have a well-settled solution for this?
public class Rule
{
}
public class RulesManager
{
List<Rule> rules = new List<Rule>();
public List<Rule> Rules
{
get { return rules; }
set { rules = value; }
}
public void Add(Rule r)
{
rules.Add(r);
// Do something else after add;
}
public void Delete(Rule r)
{
rules.Remove(r);
// Do something else after delete;
}
}
public class CallingCode
{
public static void Main()
{
RulesManager r = new RulesManager();
// Option 1
r.Rules.Add(new Rule());
// Option 2
r.Add(new Rule());
}
}

Instead of returning a Clone, you can return a read-only version of rules using rules.AsReadOnly().
public IList<Rule> Rules
{
get { return rules.AsReadOnly(); }
// set { rules = value; -- should not be allowed to set if read only!
}
Note the IList.

Instead of returning a List you can return an IEnumerable. The IEnumerable allows the user to iterate through the collection, but it doesn't allow the user to modify it easily.
Alternatively you could return an arryay instead of a list. This will create a copy of the list that the user cannot easily modify.
Finally you should be aware that the user might also modify the contents of the collection. This may be what you want, but you might also want to return copies of your items.

I think it is quite common to expose the IList as a property, but I prefer to expose only explicit Add/Delete functions. You can also consider to implement one of the collection interfaces in your class (IList for instance), if you are developing something more of a framework.
Instead of:
public List<Rule> Rules
{
get { return rules; }
set { rules = value; }
}
I prefer to implement IEnumerable<T> and an indexer on the class, so that I have control over what happens to the list.

Check out the ReadOnlyCollection and the AsReadOnly() List method.

A basic workaround is to use List<T>.AsReadOnly() method, which will wrap the list around a ReadOnlyCollection to block any "write" access. Of course, you'd have to make the setter private, otherwise it would not make sense...
Another alternative would be to implement your own IList that would alert you in case of "write" access and allow you to perform your business logic.

Related

C# Unit testing. Verify list count

I wanted to have a test case where I can verify a list of IRule count increases as new IRule item added. The method I am testing is AddRule. I wanted to keep the 'rules' property private.
Here's the code
public class DefaultRulesManager : IRulesManager
{
private List<IRule> rules;
public DefaultRulesManager()
{
rules = new List<IRule>();
}
public void AddRule(IRule rule)
{
if (rule == null)
{
throw new ArgumentNullException("rule must be set");
}
rules.Add(rule);
}
public bool HasPassed<T, SKU>(T obj, SKU s)
{
IProduct product = (IProduct)obj;
return rules.All(x => x.HasPassed(product, s));
}
}
You could expose a Count read only property that returns the count of rules:
public int RulesCount
{
get { return rules.Count; }
}
There are various options here:
Expose rules publicly but safely, e.g. via a ReadOnlyCollection<T> wrapper or as an IEnumerable<IRule> via return rules.Select(r => r); to avoid the actual list being exposed via casting. This is reasonable if you have no objection to callers knowing what rules are in a manager, so long as they can't modify the list except via AddRule.
Expose rules internally (ideally via a property - I wouldn't suggest an internal field; I'd also make the field readonly), and use InternalsVisibleTo to allow your test access to that. (You could expose just the count if you want, but I'm not sure it's particularly beneficial.)
Stick to testing the public API - you can check whether all the rules you add into the list (in your test) are then consulted.
Personally I'd probably go for the former option - but some people take "only test the public API" as a golden rule never to be broken.
Yet another idea, on the top of previous answers is to perform your unit tests against a class which inherits DefaultRulesManager.
You'd have to change DefaultRulesManager class slightly by making rules member protected. Inherited class can be named DefaultRulesManagerTestable and provide public readonly property RulesCount which would return rules.Count.

Casting contents of an indexer's returned collection?

I have a table/row/column data structure setup. There is a string-based indexer in the DtaTable class to return DtaRows, and another on the DtaRow class to return DtaColumns. So you can write things like...
return theTables["tablename"]["rowidentifier"]["columnname"];
In actuality, the objects inside the tables are not DtaRows, but one of about three dozen subclasses, like InflationRow and CurrencyRow. Each table contains only objects of those types, so for instance...
theTables["Inflations"]["General"];
always returns an InflationRow.
Now to make this easier to access from C#, I have a bunch of methods at a higher level like...
public DtaTable Inflations { get {return pTables["Inflations"];} }
Now the problem I'd like to solve is that when someone calls one of these methods, they don't get an InflationRow, because DtaTable has DtaRows. So for instance...
MyInfRow = Inflations["General"];
returns a DtaRow. So I have to cast all the time...
MyInfRow = (InflationRow)Inflations["General"];
I want to get rid of all the casting.
The only solution I have found so far is to make 36 new subclasses of the table object, each overriding the indexer return type. This seems worse than the casting.
Is there some simpler way to do this?
It you know that callers are only primarily going to use another indexer, you can introduce a generic class providing that:
public class SpecializedTable<T>
{
private readonly DtaTable table;
// Just in case anyone really wants this
public DtaTable Table { get; }
public SpecializedTable(DtaTable table)
{
this.table = table;
}
public T this[string row] { get { return (T) (object) table[row]; } }
}
As an aside, these DtaTable etc names feel annoying unpronounceable / easily confusable with the .NET DataTable classes. If you're in a position to rename them, I'd suggest you do so.
Then your Inflations property can be:
public SpecializedTable<InflationRow> Inflations
{
get
{
return new SpecializedTable<InflationRow>(pTables["Inflations"]);
}
}
You may want to cache this to avoid creating a new object each time you call the property though.
At that point, this code: Inflations["General"] will perform the cast appropriately for you.
Use as instead of direct cast. If casting is valid it will return the instance, otherwise it will stay as NULL.
public MyInfRow Inflations { get {return pTables["Inflations"] as MyInfRow } }

Want to make this permissioning system generic to reduce duplicate code etc

I have a bunch of enumerations that represent permissions for various parts of the application.
public enum PermissionGroup1
{
CanDo11,
CanDo12,
CanDo13,
}
public enum PermissionGroup2
{
CanDo21,
CanDo22,
CanDo23,
}
public enum PermissionGroup3
{
CanDo31,
CanDo32,
CanDo33,
}
For a given user, I have a collection of all of the user's permissions, and then to check permissions I have a method like:
public Boolean CheckXXXAccess(int ModuleID, PermissionGroupX permission)
{
bool hasAccess = false;
if (!m_Permissions.ContainsKey(ModuleID))
{
hasAccess = false;
}
else
{
hasAccess = (permission == (ModulePermissions[ModuleID].PermissionGroupX & permission));
}
return hasAccess;
}
So to explain it further, the database contains a ModuleID (there is a PermissionGroup enumeration for a given module type), and then I have a method like CheckXXXAccess for each module type.
How can I use generics to make a single method instead of repeating it?
I have implemented it this way.
Say Perms is your ModulePermissions[ModuleID] object's class. Then you could delegate checking access to it like this:
public bool CheckAccess<T>(int moduleId, T perm) {
if(!ModulePermissions.ContainsKey(moduleId)) return false;
return ModulePermissions[moduleId].HasPermission(perm);
}
The Perms implementation:
public class Perms {
List<object> perms = new List<object>();
public bool HasPermission<T>(T perm) {
return perm == (GetPerm(typeof(T)) & perm);
}
dynamic GetPerm(Type permType) {
foreach(var item in perms) {
if(item.GetType() == permType)
return item;
}
throw new Exception();
}
}
That way you can use your new CheckAccess method like this:
bool b1 = CheckAccess(1, PermissionGroup1.CanDo11);
bool b2 = CheckAccess(3, PermissionGroup3.CanDo32);
Of course, you can rewrite HasPermission and GetPerm methods depending on your code rules (e.g. without dynamic and with reflection).
IMO it's better to change your enums to classes, instead of having different enum, have different classes and one enum (with different access level for example Level1, Level2, ... may be some extra level for future), and all of this classes inherit from base class (like PermisionAccessBase) which has one method (currently with this information): CheckAccess (as virtual), and one property which is of type Access Level Enum, All other classes inherit it in the way they want (can override base method but you can have a chance to call to your base).
It doesn't reduce the number of function you should write, but you can put common part of methods in base method and call it in overrided methods, Also it causes to separation of concept, I think the class currently you using for checking permission doesn't made for check permission and if is so, all different permission type checking gathered in one class which is not good.

Return ReadOnlyCollection from IList<>

OK, so List<> contains the AsReadOnly() which gives you the ReadOnlyCollection. What I need is to have a field of IList type, and a property which would return a ReadOnlyCollection for this list.
Example class:
class Test
{
private IList<Abc> list;
public AddToList(Abc someItem) { /* adds inside the list */... }
public ReadOnlyCollection<Abc> List { get { return ??? } } // <- no "set" here!
}
The scenario is following: I need to have some custom logic inside my class when the item is added into the list, and I want to restrict adding to this list by calling AddToList(someitem), while not allowing the usage of list.Add(someItem). The problem is that I use NHibernate which requires the IList interface, so I cannot cast / call the AsReadOnly() on the IList (it does not contain this method).
What way would you recommend to solve this situation? I simply need a way for NHibernate to set the needed collection in some way, but I also need to restrict users.
You can just emulate AsReadOnly():
public ReadOnlyCollection<Abc> List
{
get { return new ReadOnlyCollection<Abc>(list); }
}
UPDATE:
This doesn't create a copy of list. ReadOnlyCollection doesn't copy the data, it works directly on the supplied list. See documentation:
A collection that is read-only is simply a collection with a wrapper that prevents modifying the collection; therefore, if changes are made to the underlying collection, the read-only collection reflects those changes.
This constructor is an O(1) operation.
try
return new ReadOnlyCollection<Abc> (list);
Use following way,
public class Test
{
private IList<SubTest> _subTests;
public virtual void AddSubTest(SubTest SubTest)
{
if (_subTests == null)
_subTests = new List<SubTest>();
_subTests.Add(SubTest);
return this;
}
public virtual IReadOnlyList<SubTest> SubTests
{
get
{
if (_subTests == null)
_subTests = new List<SubTest>();
return _subTests.AsReadOnly();
}
}
public void RemoveSubTest( SubTest SubTest )
{
if( _subTests == null )
return;
_subTests.Remove( SubTest );
}
}
use following mapping, and it would sets the value to the field not to the property which is read only list
<bag
name="SubTests" table="SubTest" lazy="true" access="field.camelcase-underscore"
optimistic-lock="false"
>
<key column ="TestID" />
<many-to-many class="SubTest, Domain" column="SubTestID" />
</bag>
You can also return IEnumerable<Abc> which is read only iterator and provide methods for adding and removing elements.
In my opinion the best way to do this is to return IEnumerable<Abc> using the method suggested by Jon Skeet:
public IEnumerable<Abc> Abcs {
get { return list.Skip(0); }
}
If you're not worried about consumers casting the IEnumerable<T> back to IList<T> you can just return IEnumerable<T>.
ReadOnlyCollection<T> has some serious flaws, the primary one being that it implements IList<T> so it does have Add and Remove methods. This can lead to runtime errors if consumers neglect to check its ReadOnly property. I strongly recommend against using it.

C#: Encapsulation of for example collections

I am wondering which one of these would be considered the cleanest or best to use and why.
One of them exposes the a list of passengers, which let the user add and remove etc. The other hides the list and only let the user enumerate them and add using a special method.
Example 1
class Bus
{
public IEnumerable<Person> Passengers { get { return passengers; } }
private List<Passengers> passengers;
public Bus()
{
passengers = new List<Passenger>();
}
public void AddPassenger(Passenger passenger)
{
passengers.Add(passenger);
}
}
var bus = new Bus1();
bus.AddPassenger(new Passenger());
foreach(var passenger in bus.Passengers)
Console.WriteLine(passenger);
Example 2
class Bus
{
public List<Person> Passengers { get; private set; }
public Bus()
{
Passengers = new List<Passenger>();
}
}
var bus = new Bus();
bus.Passengers.Add(new Passenger());
foreach(var passenger in bus.Passengers)
Console.WriteLine(passenger);
The first class I would say is better encapsulated. And in this exact case, that might be the better approach (since you should probably make sure it's space left on the bus, etc.). But I guess there might be cases where the second class may be useful as well? Like if the class doesn't really care what happens to that list as long as it has one. What do you think?
In example one, it is possible to mutate your collection.
Consider the following:
var passengers = (List<Passenger>)bus.Passengers;
// Now I have control of the list!
passengers.Add(...);
passengers.Remove(...);
To fix this, you might consider something like this:
class Bus
{
private List<Passenger> passengers;
// Never expose the original collection
public IEnumerable<Passenger> Passengers
{
get { return passengers.Select(p => p); }
}
// Or expose the original collection as read only
public ReadOnlyCollection<Passenger> ReadOnlyPassengers
{
get { return passengers.AsReadOnly(); }
}
public void AddPassenger(Passenger passenger)
{
passengers.Add(passenger);
}
}
In most cases I would consider example 2 to be acceptable provided that the underlying type was extensible and/or exposed some form of onAdded/onRemoved events so that your internal class can respond to any changes to the collection.
In this case List<T> isn't suitable as there is no way for the class to know if something has been added. Instead you should use a Collection because the Collection<T> class has several virtual members (Insert,Remove,Set,Clear) that can be overridden and event triggers added to notify the wrapping class.
(You do also have to be aware that users of the class can modify the items in the list/collection without the parent class knowing about it, so make sure that you don't rely on the items being unchanged - unless they are immutable obviously - or you can provide onChanged style events if you need to.)
Run your respective examples through FxCop and that should give you a hint about the risks of exposing List<T>
I would say it all comes down to your situation. I would normally go for option 2 as it is the simplest, unless you have a business reason to add tighter controls to it.
Option 2 is the simplest, but that lets other classes to add/remove elements to the collection, which can be dangerous.
I think a good heuristic is to consider what the wrapper methods do. If your AddPassenger (or Remove, or others) method is simply relaying the call to the collection, then I would go for the simpler version. If you have to check the elements before inserting them, then option 1 is basically unavoidable. If you have to keep track of the elements inserted/deleted, you can go either way. With option 2 you have to register events on the collection to get notifications, and with option 1 you have to create wrappers for every operation on the list that you want to use (e.g. if you want Insert as well as Add), so I guess it depends.

Categories