I have an array which really is a function, however i would like to use it as an array. I know i can write these
int var { get{return v2;} }
public int this[int v] { get { return realArray[v]; }
but how do i implement a function that like an array? i would like to do something like
public int pal[int i] { get { return i*2; } }
But that get a compile error
error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type.
error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression)
In C#, the only possible way to declare a parameterized property is an indexer. However, you could simulate something like that by creating a class that provides an indexer and adding a property of that type to your class:
class ParameterizedProperty<TProperty, TIndex> {
private Func<TIndex, TProperty> getter;
private Action<TIndex, TProperty> setter;
public ParameterizedProperty(Func<TIndex, TProperty> getter,
Action<TIndex, TProperty> setter) {
this.getter = getter;
this.setter = setter;
}
public TProperty this[TIndex index] {
get { return getter(index); }
set { setter(index, value); }
}
}
class MyType {
public MyType() {
Prop = new ParameterizedProperty<string, int>(getProp, setProp);
}
public ParameterizedProperty<string, int> Prop { get; private set; }
private string getProp(int index) {
// return the stuff
}
private void setProp(int index, string value) {
// set the stuff
}
}
MyType test = new MyType();
test.Prop[0] = "Hello";
string x = test.Prop[0];
You can extend the idea to read only and write only properties by removing getter or setter from the class as appropriate.
As you noticed, you cannot name an indexer like that, so either:
public int this[int i] { get { return i * 2; } }
Or alternatively if you are really set on naming it pal:
public class Wrapper
{
public int this[int i] { get { return i * 2; } }
}
...
public Wrapper pal { get { return _someWrapperInstance; } }
Which can then be accessed pal[ix], pal[3], etc.
Either you return an array object:
public int[] pal { get { return realArray; } }
or you return an object that has an indexer:
public class ActingAsArray {
private int[] _arr;
public ActingAsArray(int[] arr) { _arr = arr; }
public int this[int v] { get { return _arr[v]; } }
}
public ActingAsArray pal { get { return new ActingAsArray(realArray); } }
You cannot overload (overloadable operators) the bracket operator in C#. The best you can do is implement an indexer, as you have shown. As per the documentation, you must use the this keyword to implement an indexer. Indexers work much like properties, they have a getter and a setter and you can perform just about any function in the getter or setter.
If you don't mind using a bit of VB.Net, it supports parameterized properties (still beats me why it's not possible in C#, as .Net is obviously capable of doing it)
This way you could create your class in VB.Net and just reference the VB.Net DLL in your project.
This could of course get somewhat annoying if your class changes often :-/
Related
Here is my problem: there is a class that contains a inner collection (or list, or array, or something like this) of some some class and It must expose a public read-only collection of items, which are properties (or fields) of relative items in inner collection. For example:
//Inner collection consists of items of this class
class SomeClass
{
public int _age;
//This property is needed for exposing
public string Age { get { return this._age.ToString(); } }
}
//Keeps inner collection and expose outer read-only collection
class AnotherClass
{
private List<SomeClass> _innerList = new List<SomeClass> ();
public ReadOnlyCollection<string> Ages
{
get
{
//How to implement what i need?
}
}
}
I know a simple way to do this by the use of a pair of inner lists, where the second keeps values of needed properties of first. Something like this:
//Inner collection consists of items of this class
class SomeClass
{
public int _age;
//This property is needed for exposing
public string Age { get { return this._age.ToString(); } }
}
//Keeps inner collection and expose outer read-only collection
class AnotherClass
{
private List<SomeClass> _innerList = new List<SomeClass> ();
private List<string> _innerAgesList = new List<string> ();
public ReadOnlyCollection<string> Ages
{
get
{
return this._innerAgesList.AsreadOnly();
}
}
}
But I dislike this overhead. May be there is some way to do what I want with exposing interfaces. Help me, please!
Hurra!
It seems that the best solution has been found. Due to the post of Groo
this problem found its almost universal answer. Here is It (we need to add two entity):
public interface IIndexable<T> : IEnumerable<T>
{
T this[int index] { get; }
int Count { get; }
}
class Indexer <Tsource, Ttarget> : IIndexable<Ttarget>
{
private IList<Tsource> _source = null;
private Func<Tsource, Ttarget> _func = null;
public Indexer(IList<Tsource> list, Func<Tsource, Ttarget> projection)
{
this._source = list;
this._func = projection;
}
public Ttarget this[int index] { get { return this._func(this._source[index]); } }
public int Count { get { return _source.Count; } }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public IEnumerator<Ttarget> GetEnumerator()
{ foreach (Tsource src in this._source) yield return this._func(src); }
}
With them, our implementation looks like this:
//Inner collection consists of items of this class
class SomeClass
{
public int _age;
//This property is needed for exposing
public string Age { get { return this._age.ToString(); } }
}
//Keeps inner collection and expose outer read-only collection
class AnotherClass
{
private List<SomeClass> _innerList = new List<SomeClass> ();
private Indexer<SomeClass, string> _indexer = null;
public AnotherClass ()
{ this._indexer = new Indexer<SomeClass, string > (this._innerList, s => s.Age); }
public IIndexable<string> Ages { get { return this._indexer; } }
}
Thank Groo and the rest who answered. Hope, this helps someone else.
The overhead is not so significant if you consider that ReadOnlyCollection is a wrapper around the list (i.e. it doesn't create a copy of all the items).
In other words, if your class looked like this:
class AnotherClass
{
private ReadOnlyCollection<string> _readonlyList;
public ReadOnlyCollection<string> ReadonlyList
{
get { return _readonlyList; }
}
private List<string> _list;
public List<string> List
{
get { return _list; }
}
public AnotherClass()
{
_list = new List<string>();
_readonlyList = new ReadOnlyCollection<string>(_list);
}
}
Then any change to the List property is reflected in the ReadOnlyList property:
class Program
{
static void Main(string[] args)
{
AnotherClass c = new AnotherClass();
c.List.Add("aaa");
Console.WriteLine(c.ReadonlyList[0]); // prints "aaa"
c.List.Add("bbb");
Console.WriteLine(c.ReadonlyList[1]); // prints "bbb"
Console.Read();
}
}
You may have issues with thread safety, but exposing IEnumerable is even worse for that matter.
Personally, I use a custom IIndexable<T> interface with several handy wrapper classes and extension method that I use all over my code for immutable lists. It allows random access to list elements, and does not expose any methods for modification:
public interface IIndexable<T> : IEnumerable<T>
{
T this[int index] { get; }
int Length { get; }
}
It also allows neat LINQ-like extension methods like Skip, Take and similar, which have better performance compared to LINQ due to the indexing capability.
In that case, you can implement a projection like this:
public class ProjectionIndexable<Tsrc, Ttarget> : IIndexable<Ttarget>
{
public ProjectionIndexable
(IIndexable<Tsrc> src, Func<Tsrc, Ttarget> projection)
{
_src = src;
_projection = projection;
}
#region IIndexable<Ttarget> Members
public Ttarget this[int index]
{
get { return _projection(_src[index]); }
}
public int Length
{
get { return _src.Length; }
}
#endregion
#region IEnumerable<Ttarget> Members
// create your own enumerator here
#endregion
}
And use it like this:
class AnotherClass
{
private IIndexable<string> _readonlyList;
public IIndexable<string> ReadonlyList
{
get { return _readonlyList; }
}
private List<SomeClass> _list;
public List<SomeClass> List
{
get { return _list; }
}
public AnotherClass()
{
_list = new List<SomeClass>();
_readonlyList = new ProjectionIndexable<SomeClass, string>
(_list.AsIndexable(), c => c.Age);
}
}
[Edit]
In the meantime, I posted an article describing such a collection on CodeProject. I saw you've implemented it yourself already, but you can check it out nevertheless and reuse parts of the code where you see fit.
Why don't you just return IEnumerable?
If you have access to LINQ (.NET 3.5) then just use a select()
public IEnumerable<string> Ages{
get{
return _innerList.Select(s => s.stringProperty);
}
}
in this case I normaly just use IEnumerable - if the collection is readonly and you don't need the Index-functionality you can just do somehting like this:
public IEnumerable<string> Ages
{
get
{
return this._innerList.Select(someObj => someObj.Age).ToArray();
}
}
public class MyClass<T>
{
public T this[int index]
{
get
{
...
}
set
{
...
}
}
public void MyMethod<T>()
{
int middleIndex = ...;
T value = this[middleIndex ];
...
}
}
The code won't compile because of the statement in MyMethod(). Is there another way of calling the indexer ?
Edit: Modified MyMethod()
Edit2: Compilation error
Error 6 Cannot implicitly convert type 'T [C:\MyClass.cs]' to 'T [C:\MyClass.cs]'
Thanks.
Works fine for me:
public class MyClass<T>
{
public T this[int index]
{
get
{
return default(T);
}
set
{
}
}
public void MyMethod(int index)
{
T value = this[index];
}
}
Admittedly I had to introduce the index parameter into MyMethod, but I'm assuming you were wanting to get the index from somewhere... if that's not what you meant, please clarify.
This works fine for me:
public class MyClass<T>
{
List<T> _items = new List<T>();
public T this[int index]
{
get
{
return _items[index];
}
}
public void MyMethod()
{
T value = this[2];
}
}
Calling the indexer is fine, but it doesn't know which index you want. If you make index a parameter of MyMethod it will work fine.
If you're trying to get the current index or something then you need to store a private variable, wire it up in your indexer and access that.
Your edited code compiles fine...
public class MyClass<T>
{
public T this[int index]
{
get
{
...
}
set
{
...
}
}
public void MyMethod()
{
int middleIndex = ...;
T value = this[middleIndex ];
...
}
}
you're not passing in a value for the index into the method MyMethod - can you post a little more code? It looks like something is missing...
Your offending code is here:
public void MyMethod<T>()
Your class MyClass<T> already has a generic type parameter T, so the generic <T> on MyMethod is unnecessary
I have an abstract base class that holds a Dictionary. I'd like inherited classes to be able to access the dictionary fields using a convenient syntax. Currently I have lots of code like this:
string temp;
int val;
if (this.Fields.TryGetValue("Key", out temp)) {
if (int.TryParse(temp, out val)) {
// do something with val...
}
}
Obviously I can wrap this in utility functions but I'd like to have a cool, convenient syntax for accessing the dictionary fields where I can simply say something like:
int result = #Key;
Is there any way to do something like this in C# (3.5)?
You could add an indexer to your class and pass the indexer's parameter through to the dictionary.
class Foo
{
// Initialized elsewhere
Dictionary<String,String> Fields;
public Int32 this[String key]
{
String temp = null;
Int32 val = 0;
if (this.Fields.TryGetValue(key, out temp)) {
Int32.TryParse(temp, out val);
}
return val;
}
}
Then given an instance of Foo called foo you could do this:
Int32 value = foo["Key"];
How about an extension method?
public static int TryGetInt(this IDictionary dict, string key)
{
int val;
if (dict.Contains(key))
{
if (int.TryParse((string)dict[key], out val))
return val;
else
throw new Exception("Value is not a valid integer.");
}
throw new Exception("Key not found.");
}
The closer you can get to a nice syntax is using extension methods:
public static class MyDictExtensionMethods
{
public static T Get<T>(this Dictionary<string, object> dict, string key)
where T: IConvertible
{
object tmp;
if (!dict.TryGetValue(key, out tmp))
return default(T);
try {
return (T) Convert.ChangeType(tmp, typeof(T));
} catch (Exception) {
return default(T);
}
}
}
Usage:
int val = this.Fields.Get<int>("Key");
You can then create additional overloads for specific types (i.e.: types that does not implement IConvertible and need specific conversion).
Assuming that it's not always an int you want (if it is, then why isn't it a Dictionary<string, int>?) - I think something like this works and gets pretty close:
int i = #int["Key"];
string s = #string["Key"];
object o = #object["Key"];
This combines the fact that identifiers can be prefixed with # (it's usually optional, but it's required if your identifier is a reserved keyword, like int or string) with the default indexed parameter from Andrew Hare's answer.
It does require another class to be used to get the indexing - though if you wanted to use parens instead of square brackets for the key name, you could use methods instead:
int i = #value<int>("Key");
Implementation would be something like:
class DerivedClass : BaseClass {
void Main() {
int i = #int["Key"];
}
}
abstract class BaseClass {
private Dictionary<string, string> D { get; set; }
protected Indexer<int> #int = new Indexer<int>(s => int.Parse(s), this);
protected Indexer<string> #string = new Indexer<string>(s => s, this);
protected Indexer<object> #object = new Indexer<object>(s => (object)s, this);
protected class Indexer<T> {
public T this[string key] {
get { return this.Convert(this.BaseClass.D[key]); }
}
private T Convert(string value) { get; set; }
private BaseClass { get; set; }
public Indexer(Func<T, string> c, BaseClass b) {
this.Convert = c;
this.BaseClass = b;
}
}
}
Or, the method route:
class DerivedClass : BaseClass {
void Main() {
int i = #value<int>("key");
}
}
abstract class BaseClass {
private Dictionary<string, string> D { get; set; }
protected T #value<T>(string key) {
string s = this.D[s];
return Convert.ChangeType(s, typeof(T));
}
}
After reading through the language spec - if you're not tied to #, _ is a legal identifier. Combine that with indexers and you get:
int i = _["key"];
So I have the following snippet of code:
private Nullable<decimal> _excessWages;
public decimal ExcessWages
{
get
{
return _excessWages ?? CalculateExcessWages();
}
set
{
if (value != CalculateExcessWages())
_excessWages = value;
else
_excessWages = null;
}
}
So basically the behavior I'm trying to implement is if a field is left blank or is assigned a value equal the calculated one use the calculated value, otherwise store the assigned value.
I have a lot of fields that need to support overriding like this. Is this the best way to accomplish this? If not what would you suggest?
I worked on this a bit based mostly on Vlad's suggestion. Turns out you can use a single generic class to abstract this. Here is the end result:
public class Overridable<T>
{
private Func<T> _calculate;
private readonly Func<T, T, bool> _compare;
protected T _t;
public Overridable(Func<T> calculate, Func<T, T, bool> compare)
{
_calculate = calculate;
_compare = compare;
}
public T Value
{
get { return _compare(_t, default(T)) ? _calculate() : _t; }
set { _t = _compare(value, _calculate()) ? default(T) : value; }
}
}
You need to pass in a compare delegate because the type isn't known until you set it in a subclass. So a simple == isn't going to cut it. I went the easy route and used a Func delegate but this could be replaced with a normal delegate if it had to be adapted for .NET 2.0 for some reason.
You'll notice I'm using default(T) instead of null. This works because the default value for a Nullable<T> is null (or more precisely, undefined but it works out to be the same).
This doesn't prevent you from trying to declare an Overridable<T> for a non-nullable type. What you'd wind up with won't through run time errors but it isn't as useful. Trying to set a Overridable<decimal>.Value to null will get you a compiler error. While setting it to default(decimal) will cause it to revert to calculating the value.
I went this route because the properties from this the class I'm using this in needs to populate a serializable object thats eventually transmitted as xml. The schema for the xml includes numeric fields defined as a mixture of integers, decimals and strings.
You then use the Overriddable class like so:
private Overridable<decimal?> _excessWages =
new Overridable<decimal?>(CalculateExcessWages, (x,y) => x == y);
public virtual decimal? ExcessWages
{
get
{
return _excessWages.Value;
}
set
{
_excessWages.Value = value;
}
}
The only problem I ran into with this was that CalculateExcessWages is a non-static method so it can't be used in a field initializer. Since all the properties in my class are non-static I had to initialize all the backing fields in the constructor.
You can make a class wrapper for this.
class OverridableValue<T>
{
public OverridableValue<T>(Func<T> calculator)
{
_calculator = calculator;
}
private Nullable<T> _t;
private Func<T> _calculator;
public T Get()
{
return return _t ?? _calculator();
}
public void Set(T value)
{
_t = (value != _calculator()) ? value : null;
}
}
It's not so syntactically sweet, but at least saves some keystrokes.
Now you can use it like this:
class Foo
{
OverridableValue<decimal> _excessWages =
new OverridableValue<decimal>(CalculateExcessWages);
public decimal ExcessWages
{
get { return _excessWages.Get(); }
set { _excessWages.Set(value); }
}
...
}
The advantage is that the whole logic is hidden at the class.
You could do this by defining a handy set/get helper method
private static T GetUtil<T>(ref Nullable<T> value, Func<T> calc) {
return value ?? calc();
}
private static void SetUtil<T>(ref Nullable<T> value, T newValue, Func<T> calc) {
if ( newValue != calc() ) {
value = newValue
} else {
value = null;
}
}
private Nullable<decimal> _excessWages;
public decimal ExcessWages
{
get { return GetUtil(ref _excessWages, CalculateExcessWages); }
set { SetUtil(ref _excessWages, value CalculateExcessWages); }
}
That looks reasonable to my eyes. The only change I might make is to cache CalculateExcessWages(), if it is expensive to do, and ok to cache:
private Nullable<decimal> _excessWages;
private Nullable<decimal> _excessWagesCalculated;
public virtual decimal ExcessWages
{
get
{
if (_excessWagesCalculated == null)
_excessWagesCalculated = CalculateExcessWages();
return _excessWages ?? _excessWagesCalculated;
}
set
{
if (_excessWagesCalculated == null)
_excessWagesCalculated = CalculateExcessWages();
if (value != _excessWagesCalculated)
_excessWages = value;
else
_excessWages = null;
}
}
But, this is more code than yours, and I think you are looking to simplify.
I'm not entirely sure if I have all the terminology correct so forgive me if I'm wrong. I was wondering if it would be possible to send an argument(s) to the method. Take the following for example.
public item (int index)
{
get { return list[index]; }
set { list[index] = value; }
}
I know that as it is, it will error. What I'm asking is if there is some way to get it working. Any suggestions or should I figure out some way around it?
Thanks in advance.
Try this:
// This returns an instance of type "Foo",
// since I didn't know the type of "list".
// Obviously the return type would need to
// match the type of whatever "list" contains.
public Foo this[int index]
{
get { return list[index]; }
set { list[index] = value; }
}
This is C#'s indexer syntax and it has some limitations (it's not as flexible as VB.NET's parameterful properties) but it does work for your specific example.
As others have shown, you can turn it into an indexer - which can have multiple parameters, by the way.
What you can't do is name an indexer in C#... although you can in VB. So you can't have two indexers, one called Foo and the other called Bar... you'd need to write properties which returned values which were themselves indexable. It's a bit of a pain, to be honest :(
This is called indexer property
public int this [int index]
{
get { return list[index]; }
set { list[index] = value; }
}
I think what you might be looking for is:
public Something this[int index]
{
get
{
return list[index];
}
set
{
list[index] = value;
}
}
For the record, Whilst the other answers are valid, you might also want to consider using the following approach:
public IList<Something> items { get; set; }
This could then be used as follows:
Something item = myFoo.items[1];
The other answers would be used in the following, slightly different, way:
Something item = myFoo[1];
The one you want depends on what exactly you are trying to achieve, which is difficult to determine without seeing the rest of the code.
Besides the indexer that has been mentioned several times now, another possibility is to make a custom class with an indexer and return an instance of it as a property.
Example:
public class IntList
{
public IntList(IEnumerable<int> source)
{
items = source.ToArray();
Squares = new SquareList(this);
}
private int[] items;
// The indexer everyone else mentioned
public int this[int index]
{
get { return items[index]; }
set { items[index] = value; }
}
// Other properties might be useful:
public SquareList Squares { get; private set; }
public class SquareList
{
public SquareList(IntList list)
{
this.list = list;
}
private IntList list;
public int this[int index]
{
get { return list.items[index] * list.items[index]; }
}
}
}
You can use indexator for solving this problem
public object this[string name]
{
get
{
int idx = FindParam(name);
if (idx != -1)
return _params[idx].Value;
throw new IndexOutOfRangeException(String.Format("Parameter \"{0}\" not found in this collection", name));
}
set
{
int idx = FindParam(name);
if (idx != -1)
_params[idx].Value = value;
else
throw new IndexOutOfRangeException(String.Format("Parameter \"{0}\" not found in this collection", name));
}
}