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.
Related
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>
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; }
}
I have a hierarchy of classes based on an abstract Device class. The repository of all devices looks a bit like this:
class Hardware
{
public readonly DeviceCollection<Switch> Switches = ...;
public readonly DeviceCollection<Light> Lights = ...;
}
where DeviceCollection implements IEnumerable<T> where T : Device.
I need to enumerate across all devices, and my currently crappy code does this
protected override IEnumerator<Device> enumerate()
{
foreach (var light in Lights)
{
yield return light;
}
foreach (var #switch in Switches)
{
yield return #switch;
}
}
This is not robust as sometimes I add a new bit of hardware, a new DeviceCollection and it's easy to forget to add a new iteration in the above. So I figured a bit of reflection would help - lazily build a list of the DeviceCollection fields and run through that. But what would the declaration of that list look like?
private List<DeviceCollection<T>> _collections;
doesn't compile. Neither does
private List<DeviceCollection> _collections;
How do I declare this list?
Corollary: Tim S's answer - that IEnumerable is covariant - solves my immediate problem. One little glitch left (which I'm sure has a simpler solution!) is how to do the reflection. Here is my ugly ugly ugly hack:
_collections = new List<IEnumerable<Device>>();
var fields = GetType().GetFields( BindingFlags.Instance | BindingFlags.Public );
foreach (var field in fields)
{
if (field.FieldType.Name.Contains( "DeviceCollection" ))
{
_collections.Add( (IEnumerable<Device>)field.GetValue(this) );
}
}
This, because the test
if (field.FieldType == typeof(DeviceCollection<>)
doesn't work.
The declaration would be:
private List<IEnumerable<Device>> _collections;
And you could use it (after setting it up, which you already seem to have a good idea how to do) as easily as:
protected override IEnumerator<Device> enumerate()
{
return _collections.SelectMany(x => x).GetEnumerator();
}
This works because the IEnumerable<T> interface is covariant, meaning that, e.g. an IEnumerable<Switch> (which DeviceCollection<Switch> implements) can be used as an IEnumerable<Device>.
The reason that a DeviceCollection<Switch> can't be used as an DeviceCollection<Device> is that classes and collections can't be covariant - it wouldn't make sense to let you try to Add a Device to an ICollection<Switch>, because it should only contain Switches. But it makes perfect sense to get a Device out of an IEnumerable<Switch>.
I would contend that you just need a single list:
public DeviceCollection<Device> Devices { get; private set; }
and then you can return specific types with Switches for example:
public IEnumerable<Switch> Switches
{
get
{
return this.Devices.OfType<Switch>();
}
}
and so now enumerate just looks like this:
protected override IEnumerator<Device> enumerate()
{
foreach (var d in Devices)
{
yield return d;
}
}
You can declare it:
private List<DeviceCollection<Device>> _collections;
Why do you need a member variable? I'd think you could do
protected override IEnumerable<Device> enumerate()
{
... reflect to get properties of type IEnumerable<Device>
foreach (var prop in properties)
{
foreach (var device in (IEnumerable<Device>)prop.GetValue(this))
{
yield return device;
}
}
}
Per the comments on efficiency, while I disagree with them, and also disagree with the solutions that propose using a single List and OfType, if reflection is too slow/dangerous, you could simplify your original code:
public IEnumerable<Device> GetAll() {
return from list in new IEnumerable<Device>[] {Switches, Lights}
from device in list
select device;
}
I'm looking to add a "recently opened" functionality to my application, and was wondering if there was a simple built in way to do lists that "overflow". By this I mean, when you add an element beyond the capacity of the list, all the items are shifted.
Code example of desired functionality (obviously its not true, the list would actually contain A,B,C):
List<string> list = new List<string>();
//if Overflow was 2
list.Add("A");
list.Add("B");
//List now contains A,B
list.Add("C");
//List now contains B,C
Sorry for the simple question. The problem itself is obvious to solve (intail plan was to inherit from List), I just don't like having to re-invent the wheel and confuse future programmers with custom objects when the language or framework has that functionality.
As far as I know ther is no such collection in the library.
You can write this very easily, based on a List<> or an array.
// untested
class OverFlowList<T>
{
T[] _data;
int _next = 0;
public OferflowList(int limit)
{
_data = new T[limit];
}
void Add(T item)
{
_data[_next] = item;
_next = (_next + 1) % _data.Length;
}
}
You can do this easily with LinkedList<T>:
LinkedList<string> list = new LinkedList<string>();
//if Overflow was 2
list.AddFirst("A");
list.AddFirst("B");
list.AddFirst("C");
list.RemoveLast();
I would, personally, wrap this into a class that you could use, ie:
public class OverflowCollection<T> : IEnumerable<T>
{
private int max;
private LinkedList<T> list = new LinkedList<T>();
public OverflowCollection(int maxItems)
{
this.max = maxItems;
}
public void Add(T item)
{
this.list.AddFirst(item);
if (this.list.Count > max)
this.list.RemoveLast();
}
// Implement IEnumerable<T> by returning list's enumerator...
}
This provides a very simple method, which has some nice advantages, including being able to change the overload amount at runtime, etc..
Use a custom class that implement IList then when implement Add method check your constraint and do it.
Before posting my question, I would like to tell you that I have no prior experience in .Net technologies and have recently started to learn C# (and WPF). My company is looking to move onto .Net technologies and I am the only one in my team learning it, so have noone apart from you guys to discuss or ask something. So if my questions are too stupid or basic at best, please bear with me.
I was trying to create a generic linked list class to allow creation of linked lists of different types. I wrote the following code and would like to have your advise on whether I have written this code properly or not. Any suggestions to improve the code in any way is most welcome.
Main program
class Program
{
static void Main(string[] args)
{
GenLinkedList<string> list = new GenLinkedList<string>("abc");
list.AddtoList("def");
int i = 0;
string[] arr = new string[10];
list.LinkedList.CopyTo(arr,0);
for (i = 0; i < list.LinkedList.Count; i++)
{
Console.WriteLine(arr[i]);
}
GenLinkedList<int> listInt = new GenLinkedList<int>(1);
listInt.AddtoList(2);
i = 0;
int[] arrInt = new int[10];
listInt.LinkedList.CopyTo(arrInt, 0);
for (i = 0; i < listInt.LinkedList.Count; i++)
{
Console.WriteLine(arrInt[i]);
}
}
}
Class GenLinkedList
public class GenLinkedList<T>
{
private LinkedList<T> _linkedlist;
public GenLinkedList(T a)
{
_linkedlist = new LinkedList<T>();
_linkedlist.AddLast(a);
}
public LinkedList<T> LinkedList
{
get
{
return _linkedlist;
}
}
public void AddtoList(T a)
{
LinkedList.AddLast(a);
}
}
Why not use System.Collections.Generic.LinkedList<T>? You're using it internally in your GenLinkedList<T> already and it's already Generic for you.
It's the Framework Provided Generic Doubly Linked List implementation. Read up on it at:
MSDN - LinkedList(T) Class
If you're creating a Generic Linked List as an exercise, you shouldn't base your implementation of of an existing Generic Linked List. You're really not going to be learning anything by wrapping something that already does exactly what you need to do.
1
A generic linked list implementation already exists in the .NET framework: LinkedList<T>. But you already know that; your code wraps it.
2
OK, so you know that. Why would you wrap it, then? The only functionality you appear to have implemented is AddtoList, which doesn't do anything the LinkedList<T> doesn't already do itself (after all, this is only a thin wrapper around LinkedList<T>.AddLast). What this means is that your GenLinkedList<T> class really doesn't offer the functionality of a linked list; it's basically an add-only collection (which could just as easily have been implemented with a List<T>, or a Stack<T>, or a Queue<T> -- anything, really).
3
Assuming you do have a good reason to wrap a LinkedList<T> (e.g., you're planning to add more functionality down the line that would actually leverage the behavior of a LinkedList<T> and/or -- here's a key ingredient -- you want to restrict the way calling code is able to interact with the list (e.g., no removals)), you really shouldn't expose your LinkedList<T> member at all. The purpose of a wrapper is just that: to wrap. You take an existing class and basically give it a new kind of interface. By exposing the underlying object directly, you cripple your wrapper. Any additional restrictions/validation/logic you have in your wrapper can be bypassed.
So, for example, if you want to be able to copy your list to an array, instead of doing this:
list.LinkedList.CopyTo(arr,0);
You would implement a CopyTo method within your GenLinkedList<T> class (which could simply call _linkedlist.CopyTo) and use that.
But I really think the first question you should be asking yourself is what you want to accomplish by wrapping LinkedList<T> in the first place.
The obvious question is why you don't just use LinkedList<T> directly, although it looks like you're trying to emulate a singly-linked list.
In this case, you should avoid exposing the underlying LinkedList<T> instance, since any client could manipulate it directly. I would also implement IEnumerable<T> which will make your list usable by linq.
I got this from http://msdn.microsoft.com/en-us/library/0x6a29h6.aspx
Works fine with me.
namespace GenLinkedList
{
class Program
{
static void Main(string[] args)
{
GenericList<object> list = new GenericList<object>();
// Add items to list.
list.AddHead("some string here");
list.AddHead(DateTime.Today.ToLongDateString());
list.AddHead(13);
list.AddHead(13.005);
for (int x = 0; x < 10; x++)
{
list.AddHead(x);
}
// Enumerate list.
foreach (object i in list)
{
Console.WriteLine(i + " " + i.GetType());
}
Console.WriteLine("\nDone");
}
}
}
namespace GenLinkedList
{
// type parameter T in angle brackets
class GenericList<T>
{
// The nested class is also generic on T.
public class Node
{
private Node next;
// T as private member data type.
private T data;
// T used in non-generic constructor.
public Node(T t)
{
next = null;
data = t;
}
public Node Next
{
get { return next; }
set { next = value; }
}
public T Data
{
get { return data; }
set { data = value; }
}
}
private Node head;
// constructor
public GenericList()
{
head = null;
}
// T as method parameter type
public void AddHead(T t)
{
Node n = new Node(t);
n.Next = head;
head = n;
}
public IEnumerator<T> GetEnumerator()
{
Node current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
}
}