I'm using a class that has an indexer defined and would like to get the data out of it and into a simple array. Is there a better way than looping through the indexer?
The indexer:
public class MyIndexer
{
public int Foo { get; }
public int GetSize{ get; } //size of data vector
public float this[int idx] { get; set; }
}
Something like this would be nice:
float[] data = indexer.GetData();
Note that I can't change MyIndexer.
Since you can get the number of elements, you can create an extension method:
public static float[] GetData(this MyIndexer indexer)
{
return Enumerable.Range(0, indexer.GetSize).Select(i => indexer[i]).ToArray();
}
You could also just use a for loop:
public float[] GetData(this MyIndexer indexer)
{
float[] data = new float[indexer.GetSize];
for(int i = 0; i < data.Length; i++)
{
data[i] = indexer[i];
}
}
No, there is no other way than to loop through the indexes. There are many ways to do the looping, but no way around it.
Also, looping through the indexes only works if the indexer actually can return values for the indexes that you expect it to. Just because the class has an indexer doesn't mean that it has to be implemented to handle any specific indexes.
From what you have there, looping would be the only way.
I'd be pretty annoyed at the developer of the class though. There are conventions in .NET that are backed up by well known interfaces; ICollection, ICollection<T>, IList, IList<T> being particularly apt.
While arrays and string's use of Length is a near-exception, the only reason I can think of for calling GetSize, "GetSize" (or indeed, for calling a property anything in the form "GetXXX") is if I knew the person who would be using the class, and I really disliked them. Not implementing ICollection<float> is a bit more likely to be justifiable, but it still is something to justify with a good reason, rather than just not bothering.
Since most classes of this nature would implement ICollection<float>, in most cases where this comes up you'd be able to do:
float[] arr = new float[indexer.Count];
indexer.CopyTo(arr, 0);
But most bizarre still is the fact that it doesn't even implement IEnumerable<float>. That's really, really weird. It's such a core part of .NET ways of doing things, that unless there's a really good reason, it's bordering on being a bug-of-omission. If it had, then you could have just done index.ToArray().
If I had to work with this object much, I'd probably write a wrapper class or at least a set of extension methods to fill in the gaps.
Related
I started to learn about C# and I usually use C++.
There is a bunch of things that I'm trying to adapt, but std::array seem like impossible...
I just want to run this kind of code:
public struct Foo {};
public struct Test
{
public Foo value[20];
};
I don't want to allocate each time I use this struct and I don't want to use a class ever...
I saw fixed keyword but it works only for basic types...
There is not equivalent to something as simple as std::array?
I can even do that in C.
How would you sove this problem? (Even if it's still dynamically alocated..)
Using a fixed size buffer (fixed) is only possible for primitive types since its use is intended for interop. Array types are reference types, and so they can have dynamic size:
public struct Test
{
public Foo[] value;
}
Note however that copying the struct will only copy the reference, so the arrays will be identical. I suggest you either make the type immutable (by disabling writing to the array), or change struct to class and control cloning explicitly.
There is no such thing as a fixed size by-value array type in C# (although I have proposed it once). The closest thing you can get to it is a value tuple.
So it seems like there is no way to not do something as stupid as dynamically allocate something know at compile time. But that's C# so I just need to... try to close my eyes.
Anyway I did something to solve array alias and fixed array at the same time (I didn't ask about array alias on this question thought).
public abstract
class Array<T>
{
private T[] data;
protected Array(int size) { data = new T[size]; }
public T this[int i]
{
get { return data[i]; }
set { data[i] = value; }
}
};
public Alias : Array<int>
{
static public int Length = 10;
public Area() : base(Length) {}
};
And some people say it's quicker to write code with C#...
If someone have better I'll glady take it!
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.
I encountered this FxCop rule before and wasn't really content with how to solve violations (thread1, thread2). I now have another case where I need to correct violations of the CA1819 kind.
Specifically, I have an algorithm-library that performs some analytic calculations on a curve (x,y), with a public "input object" like this:
public class InputObject
{
public double[] X { get; set; }
public double[] Y { get; set; }
// + lots of other things well
}
This object's X and Y properties are used in hundreds of locations within library, typically using indexes. The input object is never altered by the algorithms, but actually it shouldn't matter if so. Also, .Length is called pretty frequently. It's a mathematical library, and double[] is kind of the standard data type in there. In any case, fixing CA1819 will require quite some work.
I thought about using List<double>, since Lists support indexing and are quite similar to arrays but I'm not sure whether this may slow down the algorithms or whether FxCop will be happy with those Lists.
What is the best option to replace these double[] properties?
If it is read only to external consumer and consumer does not want to access it by index then the best is to have a public read only property of type IEnumerable<> with method accessors to add and remove, this way you will not have to expose your array to someone to mess with.
If you need to access the indexers then expose it as read only property of type IList<> and probably return a ReadOnly instance, with methods to add and remove.
This way you keep encapsulation of the internal list and allow consumer to access it in a read only way
Sometime FxCop from my point of view exagerates.
It all depends on what you have to do, if you are writing a complex system where security and very clean code is required, you should returns a readonly version of that array.
That is, cast the array as IEnumerable as suggests devdigital or use the good idea ImmutableArray of Mohamed Abed, that i prefer.
If your are writing software that require high performance... there is nothing better than an array for performances in C#.
Arrays can be a lot more performant for iterating and reading.
If performances are really important I suggest you to ignore that warning.
Is still legal, also if not too much clean, to return a readonly array.
for (int i = 0; i < array.Length; ++i) { k = array[i] + 1; }
This is very fast for big arrays in C#: it avoids array bounds check.
It will perform very much as a C compiled code would do.
I always wished a "readonly array" type in C# :) but there is no hope to see it.
As your link suggests:
To fix a violation of this rule, either make the property a method or
change the property to return a collection.
Using a collection such as a List should not have a significant impact on performance.
The big problem here isn't really what your library does with the values (which is a potential problem, albeit a much more manageable one), but rather what callers might do with the values. If you need to treat them as immutable, then you need to ensure that a library consumer cannot change the contents after their original assignment. The easy fix here would be to create an interface that exposes all the array members that your library uses, then create an immutable wrapper class for an array that implements this interface to use in your InputObject class. e.g.:
public interface IArray<T>
{
int Length { get; }
T this[int index] { get; }
}
internal sealed class ImmutableArray<T> : IArray<T>
where T : struct
{
private readonly T[] _wrappedArray;
internal ImmutableArray(IEnumerable<T> data)
{
this._wrappedArray = data.ToArray();
}
public int Length
{
get { return this._wrappedArray.Length; }
}
public T this[int index]
{
get { return this._wrappedArray[index]; }
}
}
public class InputObject
{
private readonly IArray<double> _x;
private readonly IArray<double> _y;
public InputObject(double[] x, double[] y)
{
this._x = new ImmutableArray<double>(x);
this._y = new ImmutableArray<double>(y);
}
public IArray<double> X
{
get { return this._x; }
}
public IArray<double> Y
{
get { return this._y; }
}
//...
}
The elements in your "immutable" array contents would still be mutable if T is mutable, but at least you're safe for the double type.
Change array [] to IEnumerable:
public class InputObject
{
public IEnumerable<double> X { get; set; }
public IEnumerable<double> Y { get; set; }
// + lots of other things well
}
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.
I have what amounts to a multi-dimensional array.
int[][][] MyValues;
What I want is to access the indexes via a strongly typed equivelent, such as an enumeration. I'm aware that you can get the enumeration values from the Enum type, but it's a bit long winded for my tastes.
I'd rather have a way to Strongly type the indexes.
For example:
int CarNumber = MyValues[Racetrack.Daytona][Race.Daytona500][Driver.JGordon];
This would, by virtue of it being enum-like, prevent any out of bounds exceptions from being thrown, plus it gives all the indexes a nice human readable meaning.
I've implemented this using a dictionary approach, but it seems kind of heavy handed:
Dictionary<Racetrack,Dictionary<Race,<Dictionary<Driver,int>>> =
new Dictionary<Racetrack,Dictionary<Race,<Dictionary<Driver,int>>>();
which I can then access via enums, but I don't really like this approach. It seems "ugly".
I'm looking for some alternate methods to represent what is essentially a multi-dimensional array while using human readable indexers, while maintaining type safety (can't accidently use a Driver for a Race, for instance, so simply using consts is not a good approach).
Any suggestions?
This will be a compile time array (example above is not real, just an illustration) so I don't have to worry about inserts or deletes or other manipulations of the array. It will stay immutable, both in values, size and layout.
Using a static class with const values is not a good approach either, since it doesn't enforce that only the set of values defined can be passed as indexers.
It sounds to me that you want to use indexers rather than an array. Assuming the following enums (Formula 1 based!):
public enum Track
{
Spielberg,
Adelaide,
Casablanca,
Liverpool,
Melbourne,
Berlin,
Sakhir,
}
public enum Constructor
{
BMW,
Ferrari,
McLaren,
Toyota,
Williams
}
public enum Driver
{
Hamilton,
Kovalainen,
Raikkonen,
Nakajima,
Glock
}
the basic structure is as follows:
public class Race
{
int Year { get; set; }
Track Track { get; set; }
Driver[] Placings { get; set; }
public int this[Driver driver] { } // placing by driver
}
public class Results
{
YearResults this[int index] { }
DriverResults this[Driver index] { }
TrackResults this[Track index] { }
ConstructorResults this[Constructor index] { }
}
public class YearResults
{
YearDriverResults this[Driver index] { }
}
This of course is a partial implementation but you can do some pretty cool things with indexers this way. Like you can access your information with any combination of values in any order (assuming you set up all the intermediate classes).
Its wordier than a multidimensional array or a tuple-keyed Dictionary but I think will give you far more elegant code.
How about using a triple <Racetrack,Race,Driver> as the key (define your own class) in the Dictionary?
If you really need to use an array, I don't think you can do better than wrapping it in a custom class that allows access only using Racetrack, Race, Driver enums.
Obvious question.. Will List<T> not work for you?
Are the enums reasonably small, with values 0...n? If so, you could use a multi-dimensional array but expose an indexer. Note that the code below uses a rectangular array rather than a jagged array, but you could fairly easily adapt it.
// In a static class somewhere. Just a convenience method to check
// whether a value is defined or not. See comment in indexer.
public static void CheckDefined<T>(this T value, String name)
where T : struct
{
if (!Enum.IsDefined(typeof(T), value))
{
throw new ArgumentOutOfRangeException(name);
}
}
// Somewhere else...
private static int GetLength<T>() where T : struct
{
return Enum.GetValues(typeof(T)).Length;
}
private int[,,] array = new int[GetLength<Racetrack>(),
GetLength<Race>(),
GetLength<Driver>()];
public int this Car[Racetrack racetrack, Race race, Driver driver]
{
get
{
// If you don't care about just getting an
// IndexOutOfRangeException, you could skip these three lines.
racetrack.CheckDefined("racetrack");
race.CheckDefined("race");
driver.CheckDefined("driver");
return array[(int) racetrack, (int) race, (int) driver);
}
}
I don't think the dictionary approach is bad, but it isn't elegant. If you created an alias for your dictionary of dictionary things would look better:
using RaceSetup = Dictionary<Racetrack,Dictionary<Race,<Dictionary<Driver,int>>>;
Or you could create a class that derived from the dictionary:
class RaceSetup : Dictionary<Racetrack,Dictionary<Race,<Dictionary<Driver,int>>>
{}