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.
See more on this question at Stackoverflow