Read only list of lists c# - c#

In general terms, a program I'm making involves storing a small number of entries (probably less than 30 at any given time) which can be categorized. I want to allow these entries to be seen but not altered from outside the class using them. I made a class called Entry which could be modified and another called ReadOnlyEntry which is a wrapper for an Entry object. The easiest way to organize these Entry objects it seems is to create a List<List<Entry>>, where each List<Entry> is a category. But then exposing that data in a readonly way became messy and complicated. I realized I would have to have one object of each of the following types:
List<List<Entry>> data;
List<List<ReadOnlyEntry>> // Where each ReadOnlyEntry is a wrapper for the Entry in the same list and at the same index as its Entry object.
List<IReadOnlyCollection<ReadOnlyEntry>> // Where each IReadOnlyCollection is a wrapper for the List<ReadOnlyEntry> at the same index in data.
IReadOnlyCollection<IReadOnlyCollection<ReadOnlyList>> readOnlyList // Which is a wrapper for the first item I listed.
The last item in the list would be exposed as public. The first lets me change entries, the second lets me add or delete entries, and the third lets me add or delete categories. I would have to keep these wrappers accurate whenever the data changes. This seems convoluted to me, so I'm wondering if there's a blatantly better way to handle this.
Edit 1:
To clarify, I know how to use List.asReadOnly(), and the stuff I proposed doing above will solve my problem. I'm just interested in hearing a better solution. Let me give you some code.
class Database
{
// Everything I described above takes place here.
// The data will be readable by this property:
public IReadOnlyCollection<IReadOnlyCollection<ReadOnlyList>> Data
{
get
{
return readOnlyList;
}
}
// These methods will be used to modify the data.
public void AddEntry(stuff);
public void DeleteEntry(index);
public void MoveEntry(to another category);
public void AddCategory(stuff);
public void DeleteCategory(index);
}

You can use List<T>.AsReadOnly() to return ReadOnlyCollection<T>.
Also, you're torturing the List<T> class storing the data the way you are. Build your own hierarchy of classes which store your individual lists.

.NET collections should support covariance, but they don't support it themselves (instead some interfaces support covariance https://msdn.microsoft.com/ru-ru/library/dd233059.aspx). Covariance means List<Conctrete> behaves like subclass of List<Base> if Concrete is subclass of Base. You can use interfaces covariation or just use casting like this:
using System.Collections.Generic;
namespace MyApp
{
interface IEntry
{
}
class Entry : IEntry
{
}
class Program
{
private List<List<Entry>> _matrix = null;
public List<List<IEntry>> MatrixWithROElements
{
get
{
return _matrix.ConvertAll(row => row.ConvertAll(item => item as IEntry));
}
}
public IReadOnlyList<List<IEntry>> MatrixWithRONumberOfRows
{
get
{
return _matrix.ConvertAll(row => row.ConvertAll(item => item as IEntry));
}
}
public List<IReadOnlyList<IEntry>> MatrixWithRONumberOfColumns
{
get
{
return _matrix.ConvertAll(row => row.ConvertAll(item => item as IEntry) as IReadOnlyList<IEntry>);
}
}
public IReadOnlyList<IReadOnlyList<IEntry>> MatrixWithRONumberOfRowsAndColumns
{
get
{
return _matrix.ConvertAll(row => row.ConvertAll(item => item as IEntry));
}
}
public void Main(string[] args)
{
}
}
}
Thanks to Matthew Watson for pointing on errors in my previous answer version.

You could make an interface for Entry which contains only getters; you would expose elements via this interface to provide read-only access:
public interface IEntry
{
int Value { get; }
}
The writable implementation would be simply:
public sealed class Entry : IEntry
{
public int Value { get; set; }
}
Now you can take advantage of the fact that you can return a List<List<Entry>> as a IReadOnlyCollection<IReadOnlyCollection<IEntry>> without having to do any extra work:
public sealed class Database
{
private readonly List<List<Entry>> _list = new List<List<Entry>>();
public Database()
{
// Create your list of lists.
List<Entry> innerList = new List<Entry>
{
new Entry {Value = 1},
new Entry {Value = 2}
};
_list.Add(innerList);
}
public IReadOnlyCollection<IReadOnlyCollection<IEntry>> Data => _list;
}
Note how simple the implementation of the Data property is.
If you need to add new properties to IEntry you would also have to add them to Entry, but you wouldn't need to change the Database class.
If you're using C#5 or earlier, Data would look like this:
public IReadOnlyCollection<IReadOnlyCollection<IEntry>> Data
{
get { return _list; }
}

Related

What is the best practice to return List of data from public api inside class library?

I have a class library which contains a method returning List to the clients (mvc,console app etc...).
Now while I was reading Guidelines for Collections, I came to know about below point:
X DO NOT use ArrayList or List<T> in public APIs.
Currently the client which is consuming my class library api is MVC which just loops on it and perform some string.format on some properties from List<Statistics> but do not change anything on original list.
I have thought of considering IEnumerable<Statistics> but then client can also cast it to List and then manipulate it and same goes with IReadOnlyList also.
MSDN design guidelines does not state that if not ArrayList or List<T> then what should be the appropriate COLLECTION for return List of something for public API?
This is my base class which is exposed to client :
public abstract class BaseManager
{
//Other shared code
public abstract List<Statistics> GetStatistics();
}
public class Manager1 : BaseManager
{
public override List<Statistics> GetStatistics()
{
var stats = new List<Statistics>();
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
return stats;
}
}
As a rule of thumb, you want to expose to your clients as little as possible.
You also don't want to tie them to a specific implementation if you have an interface that guarantees the contract you allow them.
So, in this spirit -
If you want your client to only be able to read the data returned using a foreach loop, then return an IEnumerable<T>.
If you want your clients to have access to the count property, return an IReadOnlyCollection<T>.
If you want your client to be able to access a specific part of the data based on it's index, than return an IReadOnlyList<T>.
Please note that IReadOnlyList<T> inherits the IReadOnlyCollection<T> and this interface inherits the IEnumerable<T> - so all of these options will allow the usage of foreach, the last two will allow the usage of count (as a property), and the last one will allow the usage of an indexer.
Also, please note that your underlying type can still be a List as it implements the IReadOnlyList<T> and therefor all other interfaces I've mentioned.
Another thing to keep in mind is that the ReadOnly in this case does not mean that all the members held by the collection are immutable - you can still change the properties of them (assuming they are mutable types) - but the collection itself being immutable - you can't add or remove items to / from it.
Update
Following your comment:
If the IEnumerable<T> is a list you can down-cast it:
IEnumerable<int> myIEnum = new List<int>();
var myList = (List<int>)myIEnum;
But the ToList() extension method only creates a list that is a copy of the original IEnumerable<T>.
If your base class would be:
public abstract class BaseManager
{
//Other shared code
public abstract IEnumerable<Statistics> GetStatistics();
}
The derived classes can still use a list inside the method, but will return it as an IEnumerable<Statistics>:
public class Manager1 : BaseManager
{
public override IEnumerable<Statistics> GetStatistics()
{
var stats = new List<Statistics>();
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
return stats;
}
}
If you want to actually create an IEnumerable that can't be down-cast to a list you can always do this:
public override IEnumerable<Statistics> GetStatistics()
{
var stats = new List<Statistics>();
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
foreach(var stat in stats)
{
yield return stat;
}
}
If you are familiar with .Net, you may notice there are a lot class with the name of _______Collection. They match the conditions in the article, so I think they are what the guideline recommends.
Such as:
System.Collections.Specialized.NameValueCollection
System.Text.RegularExpressions.MatchCollection
System.Collections.Generic.Dictionary.KeyCollection
So what they suggest are
Create one like StatisticsCollection
Implement a collection interface like ICollection<Statistics>

C# Base class with static list to be different between instantiated types?

I have a need to create unique ID's for my objects which can be saved and loaded between application instances.
I have this working in my current implementation but it means each of my classes needs almost the same piece of code, therefore I decided to create a base class with this code in and then inherit from that. The code is below. The only issue I'm having is that because I have a static list in the base class, all inherited class types are getting added to the same list.
Therefore how can I change the code so that the List 'items' is a different list between types?
To clarify. If I have two classes list this:
Foo: UniqueObject
Bar: UniqueObject
I want to the Foo and Bar to have their own static item list
abstract class UniqueObject
{
static protected List<UniqueObject> items = new List<UniqueObject>();
static Random rnd = new Random();
int id;
public int Object_ID { get { return id; } }
protected UniqueObject()
{
id = generateUniqueID();
items.Add(this);
}
protected UniqueObject(int Object_ID)
{
// Ensure the passed ID is unique
if (!isIdUnique(Object_ID))
{
// if not it does not get added to the items list and an exception is thrown.
throw new ArgumentNullException("Object ID is not unique. Already being used by another object.");
}
// If we get here then must have been unique so add it.
items.Add(this);
}
/// <summary>
/// Generates the unique identifier.
/// </summary>
/// <returns>The unique ID</returns>
private int generateUniqueID()
{
// get a random number
int val = rnd.Next();
// check it is unique, if not get another and try again.
while (!isIdUnique(val))
{
val = rnd.Next();
}
return val;
}
/// <summary>
/// Checks that the passed ID is unique against the other
/// objects in the 'items' list.
/// </summary>
/// <param name="ID">The identifier.</param>
/// <returns></returns>
private bool isIdUnique(int ID)
{
foreach (UniqueObject c in items)
{
if (c.id == ID)
return false;
}
return true;
}
}
I believe I can achieve this using Generics so i could change the class and list to something like this:
abstract class UniqueObject<T>
{
static protected List<T> items = new List<T>();
But this gives other errors with the line items.Add(this).
Any help would be appriciated.
On your last remark about using generics, I guess you could do this:
abstract class UniqueObject<T> where T : class
And then
items.Add(this as T);
This should work, and this as T should never fail on runtime if you don't explicitly use UniqueObject<>.
I'm not sure about how I feel about advocating having static members on generic types (and you should not do that), but this should at least work
Update: yes, it seems to work
Recommendation
In my answer, I tried to answer exactly what you were asking. But with all this said, if all you need is a unique ID for your objects and checking if it's not duplicated when you create them, you could:
Use a GUID, and forget about checking. GUID collisions are theoretically possible.... but will it happen? Under normal conditions, more likely not. Even if you created a trillion GUIDs in a year, there's a higher chance your program will crash by a meteorite striking the computer several times before you find a duplicate
Still, if you want to check it and make absolutely sure (which is a fair thing to do, actually), this could be way easier, and you don't need to store a list of the whole objects per-type to do this... see this simple base class, which will do what you want in a similar way you are doing it:
abstract class UniqueObject : IDisposable
{
static protected HashSet<Guid> Guids = new HashSet<Guid>();
Guid _id;
public Guid ObjectID { get { return _id; } }
protected UniqueObject()
{
do
{
_id = Guid.NewGuid();
} while(Guids.Contains(_id));
Guids.Add(_id);
}
protected UniqueObject(Guid guid)
{
if(Guids.Contains(guid))
throw new ArgumentNullException("Object ID is not unique. Already being used by another object.");
_id = guid;
}
// Make a better implementation of IDisposable
public void Dispose()
{
guids.Remove(_id);
}
}
And that's it. If you still want to use int instead of Guid, you could just change it to int, and have something like:
// static members
static protected Random rnd = new Random();
static protected HashSet<int> ids = new HashSet<int>();
// ... in the constructor:
do
{
_id = rnd.Next();
} while(ids.Contains(_id));
Which looks similar to what you had before
If you want an unique id that has the folowing properties:
1) Is unique in current app domain
2) Values are unique even when dealing with multiple instances of your application.
Then you need to consider one of these solutions:
1) Generate GUIDS
2) Have a unique "server" for your generated ids (a common server that can serve your ids)
3) If you know exactly how many application instances you have, you can define a "series" of unique ids for each instance.
And last, you need to abstract the notion of unicity into a separate service that you can move around in whatever tier / layer of your application. Your objects must NOT contain logic about unicity, this notion is a separate concern and you must be deal with it in other component. Please apply the separation of concerns pattern.
So this is my implementation (if I would be you)
public interface IEntityWithUniqueId
{
void SetUniqueId(string uniqueId);
string UniqueId { get; }
}
public interface IUniqueIdsProvider
{
string GetNewId();
}
public class UniqueObject : IEntityWithUniqueId
{
public string UniqueId { get; private set; }
void IEntityWithUniqueId.SetUniqueId(string uniqueId)
{
UniqueId = uniqueId;
}
}
public class MyObjects : UniqueObject
{
}
public class RemoteUniqueIdsProvider : IUniqueIdsProvider
{
public string GetNewId()
{
// calling a service ...., grab an unique ID
return Guid.NewGuid().ToString().Replace ("-", "");
}
}
public class UniqueObjectsFactory<T> where T : IEntityWithUniqueId, new ()
{
private IUniqueIdsProvider _uniqueIdsProvider;
public UniqueObjectsFactory(IUniqueIdsProvider uniqueIdsProvider)
{
_uniqueIdsProvider = uniqueIdsProvider;
}
public T GetNewEntity()
{
var x = new T();
x.SetUniqueId(_uniqueIdsProvider.GetNewId ());
return x;
}
}
I wrote a test method like this:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void UniqueObjectTest()
{
var provider = new RemoteUniqueIdsProvider();
var factory = new UniqueObjectsFactory<MyObjects>(provider);
var entity = factory.GetNewEntity();
var entity2 = factory.GetNewEntity();
Assert.AreNotEqual(entity.UniqueId, entity2.UniqueId);
}
}
To explain what is above:
1) The interface IEntityWithUniqueId defines how an "unique" object must look like in your application, so it is an object that has an UniqueId property and also a special method: SetUniqueId. I didn't made the property UniqueId with get and set because "set" would be an infrastructure operation but get will be a developer API.
2) The interface IUniqueIdsProvider tells you how a unique ids provider will look like. It must have a simple method: GetNewId (); that serves you an unique Id. The implementation can be anywhere (on a server, locally, etc)
3) UniqueObject class. This class is the base class for all your unique objects.
4) UniqueObjectsFactory. This is the class that serves you new unique objects. When loading objects from disk, you must start from the asumption that you GENERATED unique ids, so when loading them you don't have to deal with checking unicity again.

C# IEnumerator with foreach loops, best design pattern?

I know similar questions have been asked before, but I've come to a dead end while trying to find the best design pattern I can use.
I am trying to make a class-library with a factory class that provides enumerators for different items via method calls.
Note: Those items don't exist in a collection and can only be created knowing the previous one. (e.g. x(i) = x(i-1) + θ) Because of that I cannot implement those items as IEnumerable(s)
What I thought until now:
public static class AllItems {
public sealed class ItemsEnumerator: IEnumerator<Item>{
//those classes have non-public constructors
.....
}
public static ItemsEnumerator GetItemsEnumerator() {
return new ItemsEnumerator();
}
public sealed class OtherItemsEnumerator:IEnumerator<OtherItem>{
....
}
public static ItemsEnumerator GetOtherItemsEnumerator() {
return new ItemsOtherEnumerator();
}
}
this way i could do :
foreach(var item in AllItems.GetItemsEnumerator()){
//do something with item
}
which won't work, because according to c# spec ItemsEnumerator doesn't have a GetEnumerator function(To be used in a foreach statement)
If I change it to this
public static class AllItems {
public sealed class ItemsEnumerator: IEnumerator{
.....
public IEnumerator<Item> GetEnumerator() {
return this;
}
}
public static ItemsEnumerator GetItemsEnumerator() {
return new ItemsEnumerator();
}
}
Is this a good design in general, or am I missing something here?
EDIT: Clarification on c# spec limitation
I am trying to make a class-library with a factory class that provides enumerators for different items via method calls. Note: Those items don't exist in a collection and can only be created knowing the previous one. (e.g. x(i) = x(i-1) + θ) Because of that I cannot implement those items as IEnumerable(s)
You don't need to go to that level of detail - you can just use yield to achieve a "conceptual" collection without having to wire in all of the enumeration plumbing:
public IEnumerable<Item> GetItems()
{
int i = 0;
while(i < 100) // or foreach(Item item in _baseItems), etc.
{
Item item = new Item();
item.X = i;
i += 10;
yield return item;
}
}
Note that this is just for illustration to show one way of returning a "collection" of items that are generated on-the fly. You are free to adapt this to your situation in whatever way is appropriate.

List(s) objects, different member values, but sharing a "static" member within the list in C#

Here it goes my question:
I intend to create several lists of objects, being each of the objects from the same class.
However, within each of the lists, I would like the different instances of the objects to share a common member I could change from any of these instances.
Of course, each of the lists have its own "static" member.
I hope I had explained myself, I am beginner and I am not sure whether my question has an obvious solution.
Edit:
I am working on an existing code, and I make every step by doing a trial-error approach. I do not know exactly how to explain it better: I have List list1, and List list2. The set of instances within list1 will have members with different values, but I want to have a member in class A which can be modified from any instance within the list1 and to be common to all the instances in list1. Similarly for list2, but with a different "static" member that the one in list1.
I think this will roughly achieve what you are looking to do. There are many ways to change the structure of the code below to achieve different goals but basically what you will need to do is create some sort of custom list that when items are added to it, it attaches itself to those items, and removes itself from them when they are removed.
public class CustomList : IList<IItem>
{
public Object CommonMember { get; set; }
private List<IItem> _internalList = new List<IItem>();
public void Add(IItem item)
{
item.OwnedList = this;
this._internalList.Add(item);
}
public void Remove(IItem item)
{
if(this._internalList.Remove(item))
{ item.OwnedList = null; }
}
... you will need to implment more members
}
public abstract class IItem
{
public Object OwnedListCommonMember
{
get {
if(this.OwnedList != null)
{ return this.OwnedList.CommonMember; }
else { return null; }
}
}
public CustomList OwnedList { get; set; }
}

Easy creation of properties that support indexing in C#

In C# I find indexed properties extremely useful. For example:
var myObj = new MyClass();
myObj[42] = "hello";
Console.WriteLine(myObj[42]);
However as far as I know there is no syntactic sugar to support fields that themselves support indexing (please correct me if I am wrong). For example:
var myObj = new MyClass();
myObj.field[42] = "hello";
Console.WriteLine(myObj.field[42]);
The reason I need this is that I am already using the index property on my class, but I have GetNumX(), GetX(), and SetX() functions as follows:
public int NumTargetSlots {
get { return _Maker.NumRefs; }
}
public ReferenceTarget GetTarget(int n) {
return ReferenceTarget.Create(_Maker.GetReference(n));
}
public void SetTarget(int n, ReferenceTarget rt) {
_Maker.ReplaceReference(n, rt._Target, true);
}
As you can probably see exposing these as one indexable field property would make more sense. I could write a custom class to achieve this every time I want the syntactic sugar but all of the boilerplate code just seem unnecessary.
So I wrote a custom class to encapsulate the boilerplate and to make it easy to create properties that can be indexed . This way I can add a new property as follows:
public IndexedProperty<ReferenceTarget> TargetArray {
get {
return new IndexedProperty<int, ReferenceTarget>(
(int n) => GetTarget(n),
(int n, ReferenceTarget rt) => SetTarget(n, rt));
}
}
The code for this new IndexedProperty class looks like:
public class IndexedProperty<IndexT, ValueT>
{
Action<IndexT, ValueT> setAction;
Func<IndexT, ValueT> getFunc;
public IndexedProperty(Func<IndexT, ValueT> getFunc, Action<IndexT, ValueT> setAction)
{
this.getFunc = getFunc;
this.setAction = setAction;
}
public ValueT this[IndexT i]
{
get {
return getFunc(i);
}
set {
setAction(i, value);
}
}
}
So my question is: is there a better way to do all of this?
Well to be specific, is there a more idiomatic way in C# to create an indexable field property, and if not how could I improve my IndexedProperty class?
EDIT: After further research, Jon Skeet calls this a "named indexer".
EDIT FOR 2022: This continues to get votes, but it probably isn't something I would use today primarily because it does push garbage collection in a way that would not be ideal at scale, if the property was being hit a lot. I remember this being a complicated topic, and I do not want to go deep on researching it right now, but I wonder if indexers could solve this problem today. See: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/indexers/
I found your idea useful, so I extended it. This may not technically be a proper answer since I'm not sure it squarely answers your question, but I thought it might be useful to people who came here looking for property indexers.
First, I needed to be able to support get-only and set-only properties, so I made a slight variation of your code for these scenarios:
Get and Set (very minor changes):
public class IndexedProperty<TIndex, TValue>
{
readonly Action<TIndex, TValue> SetAction;
readonly Func<TIndex, TValue> GetFunc;
public IndexedProperty(Func<TIndex, TValue> getFunc, Action<TIndex, TValue> setAction)
{
this.GetFunc = getFunc;
this.SetAction = setAction;
}
public TValue this[TIndex i]
{
get
{
return GetFunc(i);
}
set
{
SetAction(i, value);
}
}
}
Get Only:
public class ReadOnlyIndexedProperty<TIndex, TValue>
{
readonly Func<TIndex, TValue> GetFunc;
public ReadOnlyIndexedProperty(Func<TIndex, TValue> getFunc)
{
this.GetFunc = getFunc;
}
public TValue this[TIndex i]
{
get
{
return GetFunc(i);
}
}
}
Set Only:
public class WriteOnlyIndexedProperty<TIndex, TValue>
{
readonly Action<TIndex, TValue> SetAction;
public WriteOnlyIndexedProperty(Action<TIndex, TValue> setAction)
{
this.SetAction = setAction;
}
public TValue this[TIndex i]
{
set
{
SetAction(i, value);
}
}
}
Example
Here's a simple usage example. I inherit from Collection and create a named indexer, as Jon Skeet called it. This example is intended to be simple, not practical:
public class ExampleCollection<T> : Collection<T>
{
public IndexedProperty<int, T> ExampleProperty
{
get
{
return new IndexedProperty<int, T>(GetIndex, SetIndex);
}
}
private T GetIndex(int index)
{
return this[index];
}
private void SetIndex(int index, T value)
{
this[index] = value;
}
}
ExampleCollection in the Wild
This hastily constructed unit test shows how it looks when you ExampleCollection in a project:
[TestClass]
public class IndexPropertyTests
{
[TestMethod]
public void IndexPropertyTest()
{
var MyExample = new ExampleCollection<string>();
MyExample.Add("a");
MyExample.Add("b");
Assert.IsTrue(MyExample.ExampleProperty[0] == "a");
Assert.IsTrue(MyExample.ExampleProperty[1] == "b");
MyExample.ExampleProperty[0] = "c";
Assert.IsTrue(MyExample.ExampleProperty[0] == "c");
}
}
Finally, if you want to use the get-only and set-only versions, that looks like this:
public ReadOnlyIndexedProperty<int, T> ExampleProperty
{
get
{
return new ReadOnlyIndexedProperty<int, T>(GetIndex);
}
}
Or:
public WriteOnlyIndexedProperty<int, T> ExampleProperty
{
get
{
return new WriteOnlyIndexedProperty<int, T>(SetIndex);
}
}
In both cases, the result works the way you would expect a get-only/set-only property to behave.
Well, the simpliest is to have the property return an object which implements IList.
Remember that just because it implements IList doesn't mean it's a collection itself, just that it implements certain methods.
I think the design you've posted is the way to go, with the one difference that I would define an interface:
public interface IIndexed<IndexT, ValueT>
{
ValueT this[IndexT i] { get; set; }
}
And for common cases, I would use the class you put in the original question (which would implement this interface).
It would be nice if the base class library provided a suitable interface for us, but it doesn't. Returning an IList here would be a perversion.
This doesn't answer your question, but it's interesting to note that CIL supports making properties like you've described - some languages (For example, F#) will allow you to define them in such a way too.
The this[] indexer in C# is just a specific instance of one of these which is renamed to Item when you build your app. The C# compiler only knows how to read this one, so if you write a "named indexer" called Target in an F# library, and try to use it in a C#, the only way you could access the property is via the ... get_Target(int) and void set_Target(int, ...) methods. Sucks.
Why not have your class inherit IList then you can just use the index and add your own properties to it. Although you will still have the Add and Remove functions its not dishonest not to use them. Plus you may find it useful to have them furthur down the road.
For more information about Lists and Arrays check out:
Which is better to use array or List<>?
EDIT:
MSDN has an article on index properties you may want to take a look at. Doesn't seem to complicated just tedious.
http://msdn.microsoft.com/en-us/library/aa288464(VS.71).aspx
There is another option where you can create an alternative Add method but depending on the type of object your add method may not always be called. Explained here:
How do I override List<T>'s Add method in C#?
EDIT 2: Similar to the first post
Why don't you have a hidden list object in your class and then just create your own methods for obtaining the data. That way Add and Remove aren't seen and the list is already indexed.
Also what do you mean by "named indexer" are you looking for the equivalent of the row["My_Column_Name"]. Theres an MSDN article I found that may be useful as it seems to show the basic way to implement that property.
http://msdn.microsoft.com/en-us/library/146h6tk5.aspx
class Test
{
private List<T> index;
public T this[string name]{ get; set; }
public T this[int i]
{
get
{
return index[i];
}
set
{
index[i] = value;
}
}
}
After some research, I came up with a slightly different solution that better fitted my needs. The example is a little concocted, but it does suit what I need it to adapt it to.
Usage:
MyClass MC = new MyClass();
int x = MC.IntProperty[5];
And the code to make it work:
public class MyClass
{
public readonly IntIndexing IntProperty;
public MyClass()
{
IntProperty = new IntIndexing(this);
}
private int GetInt(int index)
{
switch (index)
{
case 1:
return 56;
case 2:
return 47;
case 3:
return 88;
case 4:
return 12;
case 5:
return 32;
default:
return -1;
}
}
public class IntIndexing
{
private MyClass MC;
internal IntIndexing(MyClass mc)
{
MC = mc;
}
public int this[int index]
{
get { return MC.GetInt(index); }
}
}
}

Categories