Strange C# property definition(indexer) - c#

How is this different from a normal property in C#?
public new Point3D this[int index]
{
get { return base[index]; }
set
{
base[index] = value;
CollectionModified();
}

This is an indexer; instead of being used as obj.Foo, it is used as obj[index], i.e.:
var oldVal = obj[1];
obj[1] = newVal;
It is "different" because:
it has no explicit name
it accepts a parameter (or parameters)
note that the indexer parameters do not have to be integers; the can be all sorts:
Dictionary<string, decimal> lookup = ...
string employeeKey = "000006";
decimal salary = lookup[employeeKey];

This is an indexer property, a kind of property that lets your custom class participate in expressions that pass array subscripts in square brackets.
This indexer replaces an indexer property of its base class (likely, a collection), which must also have an indexer property. The getter forwards the call to the base, while the setter also calls CollectionModified, presumably to notify whomever is watching for modifications in the collection.

It is an Indexer. It works like this (No need to call any property):
yourPoints[0] = new Point3D();
Point3D point = yourPoints[0];

Related

Can someone explain this C# syntax?

What's actually going on here:
public decimal[] Coefficients;
public decimal this[int i]
{
get { return Coefficients[i]; }
set { Coefficients[i] = value; }
}
What does the this serve as? Is it some sort of extension to the decimal?
It's 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.
Example from the linked MSDN:
class SampleCollection<T>
{
// Declare an array to store the data elements.
private T[] arr = new T[100];
// Define the indexer, which will allow client code
// to use [] notation on the class instance itself.
// (See line 2 of code in Main below.)
public T this[int i]
{
get
{
// This indexer is very simple, and just returns or sets
// the corresponding element from the internal array.
return arr[i];
}
set
{
arr[i] = value;
}
}
}
// This class shows how client code uses the indexer.
class Program
{
static void Main(string[] args)
{
// Declare an instance of the SampleCollection type.
SampleCollection<string> stringCollection = new SampleCollection<string>();
// Use [] notation on the type.
stringCollection[0] = "Hello, World";
System.Console.WriteLine(stringCollection[0]);
}
}
// Output:
// Hello, World.
It is an indexer it will be called when you use syntax like obj[1]. https://msdn.microsoft.com/en-us/library/6x16t2tx.aspx
Have you ever wondered how List<T>'s myList[i] works in c# just like an array ?
The Answer is in your question. The syntax you posted is a syntactic sugar that the compiler transforms into properties called get_Item(int index) and set_Item(int index, decimal value). It is used in List<T> for example to access the internal array used in the class and return the element at the specified index (set or get). This feature is called an Indexer.
To test that yourself, try to create a method with same signature :
public decimal get_Item(int i)
{
return 0;
}
You'll get a compiler error :
Error CS0082: Type 'MyClass' already reserves a member called
'get_Item' with the same parameter types

Test if generic type supports ICloneable

I have a structed called ValueFrequency which starts its life as a struct where you (for statistical reasons) could store a (double) value, and an (int) frequency (telling how many times this value occured in a set of data. E.g. if you had a list/array with the values: 1,1,1,2,2,3,4,4,4,4,4 it could be stored as a list/array of ValueFrequency in stead: (1,3),(2,2),(3,1),(4,5).
Anyway I found in stead of hardcoding my scruct to use double I could use a generic, so I could use it with outher data-types (e.g. a Point, when using it to store data from a 2-dimentional set of data).
Simplified version of the struct:
public struct ValueFrequency<T> : IComparable, ICloneable where T : IComparable
{
public T value;
public int Frequency;
}
My problem is I want to use this struct with both structs/classes supporting ICloneable and ValueTypes like double. How would I write a copy-constructor (copying its fields from another ValueFrequncy), where it will either simply assign the same value (if type is ValueType) or Clone if the struct/class supports IClonable:
public ValueFrequency(ValueFrequency<T> valueFrequency)
{
if (typeof(T).IsValueType)
this.Value = valueFrequency.Value;
else if (T is supporting IClonable) // pseudo-code ???
this.Value = (T)valueFrequency.Value.Clone();
else
throw new Exception("T must be ValueType or IClonable") ;
this.Frequency = valueFrequency.Frequency;
}
As you can see my problem is testing for if T is IClonable, and the actual cloning (typecasts T to IClonable to perform the cloneing).
Do you care that the type implements ICloneable or just that the underlying object is an ICloneable?
else if (valueFrequency.Value is ICloneable)
this.Value = (T)((ICloneable)valueFrequency.Value).Clone();
You can use the IsAssignableFrom method like this:
bool is_cloneable = typeof(ICloneable).IsAssignableFrom(typeof(T));
Or you could cast valueFrequency.Value as ICloneable and test if it is not null like this:
ICloneable value_as_cloneable = valueFrequency.Value as ICloneable;
if(value_as_cloneable != null)
this.Value = (T)value_as_cloneable.Clone();
Thanks to the both of you (Yacoub Massad and D Stanley), I ended up implementing both of your solutions. I decided on the following
implementation of my (copy)Constructor (which implements the suggestions of D Stanley):
public ValueFrequency(ValueFrequency<T> valueFrequency)
{
if (valueFrequency.Value is ICloneable)
Value = (T)((ICloneable)valueFrequency.Value).Clone();
else
Value = valueFrequency.Value;
_frequency = valueFrequency.Frequency;
}
Another method of this struct can take an IEnumerable of ValueFrequency (which holds a value (T) and a Frequency (int)) and "unpack" it into a List of values(T), where each value is repeated as many times as the Frequency (this method implements the suggestions of Yacoub Massad):
public static List<T> ListOfValueFrequencyToList(IEnumerable<ValueFrequency<T>> valueFrequencyList)
{
bool isCloneable = typeof(ICloneable).IsAssignableFrom(typeof(T));
List<T> result = new List<T>();
foreach (ValueFrequency<T> vf in valueFrequencyList)
{
for (int i = 0; i < vf.Frequency; i++)
{
if (isCloneable)
result.Add((T)((ICloneable)vf.Value).Clone());
else
result.Add(vf.Value);
}
}
return result;
}

Access property in C# via indexer

C# allows you to override the array indexer of the this property, like so:
int this[int index]
{
get { return _hidden[index]; }
set { _hidden[index] = value; }
}
int[] _hidden;
However, I'd like to access a differently named property via an index, like so:
int Hidden[int index]
{
get { return _hidden[index]; }
set { _hidden[index] = value; }
}
int[] _hidden;
I know I could work around this by using it as a regular parameter, as such:
int Hidden(int index)
{
return _hidden[index];
}
void Hidden(int index, int value)
{
_hidden[index] = value;
}
int[] _hidden;
However, I lose the convenience of a named property that way, and I'm essentially returning to publicly named get/set methods. Additionally, as I am behind the scenes accessing members of an array, the array indexing notation makes more sense conceptually for my situation.
Is there any way to combine the convenience of the operator with the array indexer?
A property cannot behave like an indexable item, unless it returns one. You have two options:
return an array, list or other item that you already have behind the scenes
create an object that provides an indexer and returns the values
The first one is simple, but it will allow changing the array/list/whatever. The second one can have only a getter, so it can be made read only.
I'm pretty sure it wouldn't be many lines of code to make a generic template with indexer and getter to encapsulate the actual object storing the values if it is needed.

Accessor for formatted sub-list of dictionary possible without creating a new object every time?

first off - yes, I had a look at this question: Is object creation in getters bad practice?.
I am also not talking about initializing an object in the accessors / mutators, it is about a specific part of the object I want to be returned in a specific way.
My question is more specific; It does not necessarily only apply to C#, however I am currently looking for a solution to implement in my C# project.
I have a class with a dictionary that maps date objects to a decimal value. In one accessor, I want to return a list of all the keys of the dictionary, another accessors returns the values.
What I also want to have is an accessor that gives me the decimal values in a specific format. It would look something like this:
class Class
{
// Some other properties...
// ....
private Dictionary<DateTime, decimal> dict;
public Class(Dictionary<DateTime, decimal> dict)
{
this.dict = dict;
}
private string FormatTheWayIWant(decimal dt)
{
// Format decimal value.
string s = String.Format("{0:F}", dt);
return s;
}
public ReadOnlyCollection<DateTime> DateTimes
{
get { return new ReadOnlyCollection<DateTime>(this.dict.Keys.ToList()); }
}
public ReadOnlyCollection<decimal> Values
{
get { return new ReadOnlyCollection<decimal>(this.dict.Values.ToList()); }
}
public ReadOnlyCollection<string> FormattedStrings
{
get
{
// Format each decimal value they way I want.
List<string> list = new List<string>();
foreach (decimal dt in dict.Keys)
{
list.Add(FormatTheWayIWant(dt));
}
return new ReadOnlyCollection<string>(list);
}
}
}
This way I can make the following calls (which is my goal!):
DateTime dateTime = DateTimes[0];
decimal s = Values[0];
string formattedS = FormattedStrings[0];
The problem with this approach is that I create a new list everytime I invoke the FormattedStrings accessor, even if I only need one of the formatted strings. I know this is not good practice and can introduce unnecessary performance issues...
The alternatives I thought of are:
I could extend the decimal class and implement a custom ToString()-method.
Or overwrite the KeyValuePair<DateTime, decimal> class and use an indexer in my class.
Or I create a method with a parameter for the index and return just the one formatted string.
Or I could have an own list for the accessor, which gets updated in the set-method for my dictionary everytime I update the dictionary.
The question I have is, is there a way to make this work with an accessor instead of a method, creating custom classes or having strange side effects on other objects when assigning a value?
Thank you in advance.
Ofcourse this can be done with an accessor. You just have to create 3 separate classes for each desired element of your processed collection. Those classes should have their own indexers, so you would be able to access the elements as a list. The difference would be, that they compute each element on demand (wchich is called lazy initialization). So it would go like this (example for your FormattedStrings):
class Class
{
// ...
MyFormattedStrings FormattedStrings
{
get {return new MyFormattedStringsIndexer<string>(this.dict.Values.ToList());}
}
}
class MyFormattedStringsIndexer<T>
{
private IList<T> list; // we take only reference, so there is no overhead
public MyFormattedStringsCollection (IList<T> list)
{
this.list = list;
}
// the indexer:
public T this[int i]
{
get
{
// this is where the lazy stuff happens:
// compute the desired element end return it
}
set
{
// ...
}
}
}
Now you can use your Class like this:
string formattedS = FormattedStrings[5];
and each element you access will be computed as you access it. This solution also has the advantage of separating concerns, so should you ever had to implement different logic for one of your 3 accessors it would be just a matter of extending one of the indexers.
You can read more about indexeres here: http://msdn.microsoft.com/en-us/library/6x16t2tx.aspx
This is VB, but you get the idea...
Public Class Something
Public Property Items As Dictionary(Of DateTime, String)
Public Readonly Property FormattedItem(ByVal index As Int32) As String
' add error checking/handling as appropriate
Return Me.Items.Keys(index).ToString("custom format") ' or whatever your formatting function looks like.
End Property
End Class
It looks like a good candidate for a new class
public class MyObject
{
public DateTime Key {get;set;}
public String Name {get;set;}
public String FormattedString {get;}
}
And then it can be used in any container (List<MyObject>, Dictionary<MyObject>, etc).
Your Dates and Strings property getters are returning a new list on each call. Therefore if a caller does the following:
Class myClass = ...
for(i=0; i<myClass.Strings.Count; i++)
{
var s = myClass.Strings[i];
...
}
then each iteration of the loop will create a new list.
I'm not clear on what you're really trying to achieve here. You are wrapping the dictionary's Keys and Values properties in ReadOnlyCollections. This gives you an indexer, which doesn't have much meaning as the order of the Keys in a Dictionary<TKey, TValue> is unspecified.
Coming (at last!) to your question, if you want to do the formatting in a "lazy" manner, you could create a custom class that implements a readonly IList<string>, and wraps your list of keys (IList<DateTime>). Most of the implementation is boilerplate, and your indexer will do the formatting. You could also cache the formatted values so that you only format once if accessed multiple times. Something like:
public class MyFormattingCollection : IList<string>
{
private IList<decimal> _values;
private IList<string> _formattedValues;
public MyFormattingCollection(IList<DateTime> values)
{
_values = values;
_formattedValues = new string[_values.Count];
}
public string this[int index]
{
get
{
var result = _formattedValues[index];
if (result == null)
{
result = FormatTheWayIWant(_values[index]);
_formattedValues[index] = result;
}
return result;
}
set
{
// Throw: it's a readonly collection
}
}
// Boilerplate implementation of readonly IList<string> ...
}

Make object that encapsulates List<> accessable via [] operator?

I have a class that I made that is basically an encapsulated List<> for a certain type. I can access the List items by using [] like if it was an array, but I don't know how to make my new class inherit that ability from List<>. I tried searching for this but I'm pretty sure I don't know how to word correctly what I want to do and found nothing useful.
Thanks!
That's called an indexer:
public SomeType this[int index] {
get { }
set { }
}
List already have a definition for the Indexer so there is no need to change that code. It will work by default.
public class MyClass : List<int>
{
}
And we can access the indexer here. Even though we havent implemented anything
MyClass myclass = new MyClass();
myclass.Add(1);
int i = myclass[0]; //Fetching the first value in our list ( 1 )
Note that the List class isn't designed to be inherited. You should be encapsulating it, not extending it. – Servy
And this would look something like
public class MyClass
{
private List<int> _InternalList = new List<int>();
public int this[int i]
{
get { return _InternalList[i]; }
set { _InternalList[i] = value; }
}
}
That's called 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.
A get accessor returns a value. A set accessor assigns a value.
The this keyword is used to define the indexers.
The value keyword is used to define the value being assigned by the set indexer.
Here is an EXAMPLE.

Categories

Resources