Related
I'd like to use indexers more, but I'm not sure when to use them. All I've found online are examples that use classes like MyClass and IndexerClass.
What about in a school system where there are Students and Teachers, and each Teacher has a list of Students that they're in charge of - any need for indexers in that scenario? For simplicity's sake: each Student can only belong to one Teacher.
Indexer is a highly specialized property which allows instances of a class (or struct) to be indexed just like an array (properties can be static but indexers cannot).
Why to use indexers:
instead of a new data structure, the class itself is a data structure.
simplified syntax - syntactic sugar
When to use:
if your class needs list(/array) of its instances (example 1)
if your class represents list(/array) of values directly related to your class (example 2)
Example 1:
public class Person{
public string Name{get; set;}
private Person[] _backingStore;
public Person this[int index]
{
get{
return _backingStore[index];
}
set{
_backingStore[index] = value;
}
}
}
Person p = new Person();
p[0] = new Person(){Name = "Hassan"};
p[1] = new Person(){Name = "John Skeet"};
Example 2:
class TempratureRecord{
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 61.3F, 56.5F, 56.9F, 58.8F, 61.3F};
public int Length{
get { return temps.Length; }
}
public float this[int index]
{
get{
return temps[index];
}
set{
temps[index] = value;
}
}
}
Heres a video i have created http://www.youtube.com/watch?v=HdtEQqu0yOY and below is a detailed explanation about the same.
Indexers helps to access contained collection with in a class using a simplified interface. It’s a syntactic sugar.
For instance lets say you have a customer class with addresses collection inside it. Now let’s say we would like to like fetch the addresses collection by “Pincode” and “PhoneNumber”. So the logical step would be that you would go and create two overloaded functions one which fetches by using “PhoneNumber” and the other by “PinCode”. You can see in the below code we have two functions defined.
Customer Customers = new Customer();
Customers.getAddress(1001);
Customers.getAddress("9090");
If you use indexer you can simplify the above code with something as shown in the below code.
Customer Customers = new Customer();
Address o = Customers[10001];
o = Customers["4320948"];
Cheers.
You typically use an indexer if the class represents a list, collection or array of objects. In your case, you could provide an indexer to provide index-based access to a teacher's students.
An indexer use in your situation would be a TeachersClass class, which would encapsulate the students (collection) and the current teacher. Although you could do the same thing by exposing the list of students, but it does show you an example.
Here is a code example:
public class TeachersClass
{
private List<Student> _students;
public TeachersClass(Teacher currentTeacher, List<Student> students)
{
CurrentTeacher = currentTeacher;
_students = students;
}
public Teacher CurrentTeacher { get; set; }
public Student this[int studentID]
{
get
{
return (from s in _students
where s.Id = studentID
select s).First();
}
}
}
Random order access
You would use an enumerator if your data is normally accessed sequentially.
An indexer on the other hand is useful for directly accessing a specific element, no specific order.
This of course assumes you know the index of the element you want. Comboboxes for example have always supported two values: the string shown to the user, and the id that belongs with it. You could use the id from a selected item in a combobox to directly access the index of your collection, instead of having to search the collection.
The nice thing about indexers in C# is that you can overload them, so you can access items through different kind of keys.
The simple answer (as stated above) is when the class represents/contains a collection of items, the indexer will return the elements of the collection.
public Student this[int index] { ..
In a more advanced case you can create a default behavior with a class and make it look a bit like a delegate, especially when the class represents a mapping, or a process. For example a class that calculates the cooling rate of a beer in the refrigerator:
Instead of typing
temperature = coorsLight.CalculateFutureTemperature(time);
you can condence this to
temperature = coorsLight[time];
if the expected behavior (and intent) of the class is to return a value.
An indexer is a means to select an element from an aggregate such as an array or collection. While I agree in part with Ian Davis, I think indexers represent something more than public API polish.
Indexers are the primary means of accessing arrays and most of the major classes representing collections in the .NET BCL implemented indexers, presumably to provide a common expernce when dealing with types that aggregate other types.
Because indexers are a standard part of the interface to many of the BCLs collection types, and because these types are heavily used, as developers learn .NET as a platform, it is reasonable to suggest that an expectation is created that collections can be accessed using some type of indexer.
If your type's interface matches the expectations that developers have already, then that type becomes easier to use because the developer doesn't have to think. This is true whether the developers in question are internal to your organization or out there in the wild.
Of course there are situations where having an indexer just doesn't make sense, and if thats the case then don't implement an indexer.
Indexers allow instances of a class or struct to be indexed just like arrays. Indexers resemble properties except that their accessors take parameters.
Indexers enable objects to be indexed in a similar manner to arrays.
// C#: INDEXER
using System;
using System.Collections;
class MyClass
{
private string []data = new string[5];
public string this [int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
}
class MyClient
{
public static void Main()
{
MyClass mc = new MyClass();
mc[0] = "Rajesh";
mc[1] = "A3-126";
mc[2] = "Snehadara";
mc[3] = "Irla";
mc[4] = "Mumbai";
Console.WriteLine("{0},{1},{2},{3},{4}",mc[0],mc[1],mc[2],mc[3],mc[4]);
}
}
Code project
I remember there was this time when I had a long inside a class, and some digits of that particular long meant something (for example if the third digit was a 3 it meant that the chart had a specific type of encoding, horrible system I know but I didn't invent it)
So I did something like this to return the xth digit of the number:
protected int this[int index]
{
get
{
int tempN = Number;
if (index > 0)
{
tempN /= index * 10;
}
return tempN % 10;
}
}
It was protected because a different method used it, so it was kind of a helper. Of course a simple GetDigit(int a) would've been the same thing (and more self-explanatory) but at the time I thought it was one of the few times I thought using an indexer would make sense. Haven't used them since =(.
IMHO, Indexers are probably best if you're trying to spruce up a packaged API - it's not worth the effort for your run of the mill business object.
And if you're making some specialized collection, I'd categorize that as sprucing up your packaged API - even if you keep it all in one module.
This is killing me because I feel like I've seen something around before, but my searches are coming up empty and I don't have various patterns committed to memory (yet).
The Situation
I have a search grid that allows users to filter based on multiple attributes. The filters that users would like are passed in via a NameValueCollection and parsed out.
Currently, our legacy app checks for each potential filter in a separate if statement and then runs custom code. And since cyclomatic complexity just isn't my thing, 30 almost identical if statements bug me.
Towards a Better Way
Rather than continuing to check each item in a hard-coded way, I've re-written the parser so that now I can quickly obtain a list of all filters that will be applied. I'm also refactoring the filters themselves into their own classes.
So, I have a list of filters in string form ("Name", "BirthDate", etc.) and a bunch of classes (NameFilter, BirthDateFilter, etc.)
The Question
What is a good, standard way to take a list of strings representing filter names and turn it into a list of those filter objects themselves?
I suppose I could do some sort of FilterLocator with a LocateFilter(string filterName) method, but that seems like it would lead to one long switch statement and seems kind of blech.
I get the sense this is heading towards some sort of IoC/DI solution, but that I don't know enough about either to fully realize it yet.
Thanks for your thoughts!
Use a dictionary where the key is your filter name, and the value is your filter object.
Rather than hard coding this dictionary, create a custom attribute that gives each filter object a filter name. Then, use reflection to find those objects and create a static dictionary that can be used later. This way, there is no hard coding of the individual filter mappings at all.
Here's a sample set up for this:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class FilterNameAttribute : Attribute
{
public FilterNameAttribute(string filterName)
{
FilterName = filterName;
}
public string FilterName { get; private set; }
}
[FilterName("MyFilterName")]
public class MyFilter
{
//Do whatever you want here
}
public static class FilterHelper
{
static Dictionary<string, Type> _filterTypesDict;
static FilterHelper()
{
var assembly = Assembly.GetExecutingAssembly();
_filterTypesDict = assembly.GetTypes()
.Select(type => new { type, attrib = (FilterNameAttribute)type.GetCustomAttributes(typeof(FilterNameAttribute), false).FirstOrDefault() })
.Where(x => x.attrib != null)
.ToDictionary(x => x.attrib.FilterName, x => x.type);
}
public static Type GetFilterType(string filterName)
{
Type filterType;
if (!_filterTypesDict.TryGetValue(filterName, out filterType))
{
throw new Exception("Unknown Filter Name.");
}
return filterType;
}
public static object GetFilter(string filterName)
{
return Activator.CreateInstance(GetFilterType(filterName));
}
}
Like in the comments I would definitely create a dictionary for your filters. Also with that I would create a base class for each filter with Name property and Apply method. And when your application starts up you can gather filter classes with reflection by the base filter class and populate the dictionary of filters using Name property as the key (or you can just use the name of the filter class), this way you don't even need to build up the dictionary manually, every time you add a filter class it will automatically appear int the dictionary. This will allow your LocateFilter(string filterName) method be really simple and straightforward.
I have the following basic entities:
public class Basket
{
public List<Product> Products {get;set;}
}
public class Product
{
public string Name {get;set;}
public decimal Price {get;set;}
}
And I want to get a list of all products in a basket that are below a fixed price. Should the logic for this go in the Basket, like so:
public class Basket
{
public List<Product> Products {get;set;}
public List<Product> CheapProducts
{
get { return Products.Where(p => p.Price < 5).ToList(); }
}
}
Or should it go in a service class, ProductFilterer, which would take the entire list of products as a parameter and would return a filtered list of products. Or maybe it should just go straight into the method of the calling class?
Or something else? What is the best practice for this?
What I would do is see with a domain expert if the notion of "cheap product" is a first class domain concept and has to be introduced in the ubiquitous language.
If this is the case, Steve's Specification solution solves your problem in an elegant way.
If cheapness is unimportant or not as clearly defined as that (for instance if the cheapness threshold varies across the application), I wouldn't bother creating a specific entity for it and just filter Basket.Products with the relevant criteria when needed in calling code.
You might consider looking into the Specification Pattern. The link has a good example implementation, but in short, the pattern allows you to create complex selection criteria based on simple predicates (or specifications).
A quick (and incomplete) implementation of such a pattern using delegates could be done as such:
public class Specification<T>
{
Func<T, bool> _spec;
public Specification(Func<T, bool> spec)
{
_spec = spec;
}
public bool IsSatisifedBy(T item)
{
return _spec(T);
}
}
// ...
_cheapProductsSpecification = new Specification<Product>(p => p.Price < 5);
var cheapProducts = Basket.Products.Where(p => _cheapProductsSpecification.IsSatifisifedBy(p));
This is, of course, a simple and probably redundant example, but if you add in And, Or, and Not (see the link), you can build complex business logic into specification variables.
Yes, I would suggest keeping your DTO's separate from the business logic. I like to think of the data objects as being a completely separate layer from the data access, business, and UI layers. If you had a more general ProductBusiness class, I would recommend just putting it in there unless it's really useful to have a separate filterer class.
Your Basket class should not know how to filter directly, it is correct for it to have an exposed function that allows it to return the results from a ProductFilter as you suggested. The way the code should look is something like this:
class ProductFilter
{
filterCheapProducts(Collection<Product> productsToFilter)
{
return Products.Where(p => p.Price < 5).ToList(); //I assume your code is correct
}
}
class Basket
{
Collection<Product> getCheapProducts()
{
return filter.filterCheapProducts(this.products);
}
}
I'd like to use indexers more, but I'm not sure when to use them. All I've found online are examples that use classes like MyClass and IndexerClass.
What about in a school system where there are Students and Teachers, and each Teacher has a list of Students that they're in charge of - any need for indexers in that scenario? For simplicity's sake: each Student can only belong to one Teacher.
Indexer is a highly specialized property which allows instances of a class (or struct) to be indexed just like an array (properties can be static but indexers cannot).
Why to use indexers:
instead of a new data structure, the class itself is a data structure.
simplified syntax - syntactic sugar
When to use:
if your class needs list(/array) of its instances (example 1)
if your class represents list(/array) of values directly related to your class (example 2)
Example 1:
public class Person{
public string Name{get; set;}
private Person[] _backingStore;
public Person this[int index]
{
get{
return _backingStore[index];
}
set{
_backingStore[index] = value;
}
}
}
Person p = new Person();
p[0] = new Person(){Name = "Hassan"};
p[1] = new Person(){Name = "John Skeet"};
Example 2:
class TempratureRecord{
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 61.3F, 56.5F, 56.9F, 58.8F, 61.3F};
public int Length{
get { return temps.Length; }
}
public float this[int index]
{
get{
return temps[index];
}
set{
temps[index] = value;
}
}
}
Heres a video i have created http://www.youtube.com/watch?v=HdtEQqu0yOY and below is a detailed explanation about the same.
Indexers helps to access contained collection with in a class using a simplified interface. It’s a syntactic sugar.
For instance lets say you have a customer class with addresses collection inside it. Now let’s say we would like to like fetch the addresses collection by “Pincode” and “PhoneNumber”. So the logical step would be that you would go and create two overloaded functions one which fetches by using “PhoneNumber” and the other by “PinCode”. You can see in the below code we have two functions defined.
Customer Customers = new Customer();
Customers.getAddress(1001);
Customers.getAddress("9090");
If you use indexer you can simplify the above code with something as shown in the below code.
Customer Customers = new Customer();
Address o = Customers[10001];
o = Customers["4320948"];
Cheers.
You typically use an indexer if the class represents a list, collection or array of objects. In your case, you could provide an indexer to provide index-based access to a teacher's students.
An indexer use in your situation would be a TeachersClass class, which would encapsulate the students (collection) and the current teacher. Although you could do the same thing by exposing the list of students, but it does show you an example.
Here is a code example:
public class TeachersClass
{
private List<Student> _students;
public TeachersClass(Teacher currentTeacher, List<Student> students)
{
CurrentTeacher = currentTeacher;
_students = students;
}
public Teacher CurrentTeacher { get; set; }
public Student this[int studentID]
{
get
{
return (from s in _students
where s.Id = studentID
select s).First();
}
}
}
Random order access
You would use an enumerator if your data is normally accessed sequentially.
An indexer on the other hand is useful for directly accessing a specific element, no specific order.
This of course assumes you know the index of the element you want. Comboboxes for example have always supported two values: the string shown to the user, and the id that belongs with it. You could use the id from a selected item in a combobox to directly access the index of your collection, instead of having to search the collection.
The nice thing about indexers in C# is that you can overload them, so you can access items through different kind of keys.
The simple answer (as stated above) is when the class represents/contains a collection of items, the indexer will return the elements of the collection.
public Student this[int index] { ..
In a more advanced case you can create a default behavior with a class and make it look a bit like a delegate, especially when the class represents a mapping, or a process. For example a class that calculates the cooling rate of a beer in the refrigerator:
Instead of typing
temperature = coorsLight.CalculateFutureTemperature(time);
you can condence this to
temperature = coorsLight[time];
if the expected behavior (and intent) of the class is to return a value.
An indexer is a means to select an element from an aggregate such as an array or collection. While I agree in part with Ian Davis, I think indexers represent something more than public API polish.
Indexers are the primary means of accessing arrays and most of the major classes representing collections in the .NET BCL implemented indexers, presumably to provide a common expernce when dealing with types that aggregate other types.
Because indexers are a standard part of the interface to many of the BCLs collection types, and because these types are heavily used, as developers learn .NET as a platform, it is reasonable to suggest that an expectation is created that collections can be accessed using some type of indexer.
If your type's interface matches the expectations that developers have already, then that type becomes easier to use because the developer doesn't have to think. This is true whether the developers in question are internal to your organization or out there in the wild.
Of course there are situations where having an indexer just doesn't make sense, and if thats the case then don't implement an indexer.
Indexers allow instances of a class or struct to be indexed just like arrays. Indexers resemble properties except that their accessors take parameters.
Indexers enable objects to be indexed in a similar manner to arrays.
// C#: INDEXER
using System;
using System.Collections;
class MyClass
{
private string []data = new string[5];
public string this [int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
}
class MyClient
{
public static void Main()
{
MyClass mc = new MyClass();
mc[0] = "Rajesh";
mc[1] = "A3-126";
mc[2] = "Snehadara";
mc[3] = "Irla";
mc[4] = "Mumbai";
Console.WriteLine("{0},{1},{2},{3},{4}",mc[0],mc[1],mc[2],mc[3],mc[4]);
}
}
Code project
I remember there was this time when I had a long inside a class, and some digits of that particular long meant something (for example if the third digit was a 3 it meant that the chart had a specific type of encoding, horrible system I know but I didn't invent it)
So I did something like this to return the xth digit of the number:
protected int this[int index]
{
get
{
int tempN = Number;
if (index > 0)
{
tempN /= index * 10;
}
return tempN % 10;
}
}
It was protected because a different method used it, so it was kind of a helper. Of course a simple GetDigit(int a) would've been the same thing (and more self-explanatory) but at the time I thought it was one of the few times I thought using an indexer would make sense. Haven't used them since =(.
IMHO, Indexers are probably best if you're trying to spruce up a packaged API - it's not worth the effort for your run of the mill business object.
And if you're making some specialized collection, I'd categorize that as sprucing up your packaged API - even if you keep it all in one module.
How would you implement a capacity-limited, generic MruList in C# or Java?
I want to have a class that represents a most-recently-used cache or list (= MruList). It should be generic, and limited to a capacity (count) specified at instantiation. I'd like the interface to be something like:
public interface IMruList<T>
{
public T Store(T item);
public void Clear();
public void StoreRange(T[] range);
public List<T> GetList();
public T GetNext(); // cursor-based retrieval
}
Each Store() should put the item at the top (front?) of the list. The GetList() should return all items in an ordered list, ordered by most recent store. If I call Store() 20 times and my list is 10 items long, I only want to retain the 10 most-recently Stored items. The GetList and StoreRange is intended to support retrieval/save of the MruList on app start and shutdown.
This is to support a GUI app.
I guess I might also want to know the timestamp on a stored item. Maybe. Not sure.
Internally, how would you implement it, and why?
(no, this is not a course assignment)
Couple of comments about your approach
Why have Store return T? I know what I just added, returning it back to me is un-necessary unless you explicitly want method chaining
Refactor GetNext() into a new class. It represents a different set of functionality (storage vs. cursor traversal) and should be represented by a separate interface. It also has usability concerns as what happens when two different methods active on the same stack want to traverse the structure?
GetList() should likely return IEnumerable<T>. Returning List<T> either forces an explicit copy up front or returns a pointer to an underlying implementation. Neither is a great choice.
As for what is the best structure to back the interface. It seems like the best to implement is to have a data structure which is efficient at adding to one end, and removing from the other. A doubly linked list would suit this nicely.
Here's a Cache class that stores objects by the time they were accessed. More recent items bubble to the end of the list. The cache operates off an indexer property that takes an object key. You could easily replace the internal dictionary to a list and reference the list from the indexer.
BTW, you should rename the class to MRU as well :)
class Cache
{
Dictionary<object, object> cache = new Dictionary<object, object>();
/// <summary>
/// Keeps up with the most recently read items.
/// Items at the end of the list were read last.
/// Items at the front of the list have been the most idle.
/// Items at the front are removed if the cache capacity is reached.
/// </summary>
List<object> priority = new List<object>();
public Type Type { get; set; }
public Cache(Type type)
{
this.Type = type;
//TODO: register this cache with the manager
}
public object this[object key]
{
get
{
lock (this)
{
if (!cache.ContainsKey(key)) return null;
//move the item to the end of the list
priority.Remove(key);
priority.Add(key);
return cache[key];
}
}
set
{
lock (this)
{
if (Capacity > 0 && cache.Count == Capacity)
{
cache.Remove(priority[0]);
priority.RemoveAt(0);
}
cache[key] = value;
priority.Remove(key);
priority.Add(key);
if (priority.Count != cache.Count)
throw new Exception("Capacity mismatch.");
}
}
}
public int Count { get { return cache.Count; } }
public int Capacity { get; set; }
public void Clear()
{
lock (this)
{
priority.Clear();
cache.Clear();
}
}
}
I would have an internal ArrayList and have Store() delete the last element if its size exceeds the capacity established in the constructor. I think standard terminology, strangely enough, calls this an "LRU" list, because the least-recently-used item is what gets discarded. See wikipedia's entry for this.
You can build this up with a Collections.Generic.LinkedList<T>.
When you push an item into a full list, delete the last one and insert the new one at the front. Most operations should be in O(1) which is better than a array-based implementation.
Everyone enjoys rolling their own container classes.
But in the .NET BCL there is a little gem called SortedList<T>. You can use this to implement your MRU list or any other priority-queue type list. It uses an efficient tree structure for efficient additions.
From SortedList on MSDN:
The elements of a SortedList object
are sorted by the keys either
according to a specific IComparer
implementation specified when the
SortedList is created or according to
the IComparable implementation
provided by the keys themselves. In
either case, a SortedList does not
allow duplicate keys.
The index sequence is based on the
sort sequence. When an element is
added, it is inserted into SortedList
in the correct sort order, and the
indexing adjusts accordingly. When an
element is removed, the indexing also
adjusts accordingly. Therefore, the
index of a specific key/value pair
might change as elements are added or
removed from the SortedList object.
Operations on a SortedList object tend
to be slower than operations on a
Hashtable object because of the
sorting. However, the SortedList
offers more flexibility by allowing
access to the values either through
the associated keys or through the
indexes.
Elements in this collection can be
accessed using an integer index.
Indexes in this collection are
zero-based.
In Java, I'd use the LinkedHashMap, which is built for this sort of thing.
public class MRUList<E> implements Iterable<E> {
private final LinkedHashMap<E, Void> backing;
public MRUList() {
this(10);
}
public MRUList(final int maxSize) {
this.backing = new LinkedHashMap<E,Void>(maxSize, maxSize, true){
private final int MAX_SIZE = maxSize;
#Override
protected boolean removeEldestEntry(Map.Entry<E,Void> eldest){
return size() > MAX_SIZE;
}
};
}
public void store(E item) {
backing.put(item, null);
}
public void clear() {
backing.clear();
}
public void storeRange(E[] range) {
for (E e : range) {
backing.put(e, null);
}
}
public List<E> getList() {
return new ArrayList<E>(backing.keySet());
}
public Iterator<E> iterator() {
return backing.keySet().iterator();
}
}
However, this does iterate in exactly reverse order (i.e. LRU first, MRU last). Making it MRU-first would require basically reimplementing LinkedHashMap but inserting new elements at the front of the backing list, instead of at the end.
Java 6 added a new Collection type named Deque... for Double-ended Queue.
There's one in particular that can be given a limited capacity: LinkedBlockingDeque.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
public class DequeMruList<T> implements IMruList<T> {
private LinkedBlockingDeque<T> store;
public DequeMruList(int capacity) {
store = new LinkedBlockingDeque<T>(capacity);
}
#Override
public void Clear() {
store.clear();
}
#Override
public List<T> GetList() {
return new ArrayList<T>(store);
}
#Override
public T GetNext() {
// Get the item, but don't remove it
return store.peek();
}
#Override
public T Store(T item) {
boolean stored = false;
// Keep looping until the item is added
while (!stored) {
// Add if there's room
if (store.offerFirst(item)) {
stored = true;
} else {
// No room, remove the last item
store.removeLast();
}
}
return item;
}
#Override
public void StoreRange(T[] range) {
for (T item : range) {
Store(item);
}
}
}