Properties exposing array elements in C# - c#

I want to create a property in C# that sets or returns an individual member of an array. Currently, I have this:
private string[] myProperty;
public string MyProperty[int idx]
{
get
{
if (myProperty == null)
myProperty = new String[2];
return myProperty[idx];
}
set
{
myProperty[idx] = value;
}
}
However, I get the following compile error:
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.

How about this: write a class that does one thing and one thing only: provide random access to elements of some underlying indexed collection. Give this class a this indexer.
For properties that you want to provide random access to, simply return an instance of this indexer class.
Trivial implementation:
public class Indexer<T>
{
private IList<T> _source;
public Indexer(IList<T> source)
{
_source = source;
}
public T this[int index]
{
get { return _source[index]; }
set { _source[index] = value; }
}
}
public static class IndexHelper
{
public static Indexer<T> GetIndexer<T>(this IList<T> indexedCollection)
{
// could cache this result for a performance improvement,
// if appropriate
return new Indexer<T>(indexedCollection);
}
}
Refactoring into your code:
private string[] myProperty;
public Indexer<string> MyProperty
{
get
{
return myProperty.GetIndexer();
}
}
This will allow you to have as many indexed properties as you want, without needing to expose those properties with the IList<T> interface.

You must use this as the property name for indexers.

C# allows only one indexed property per class, so you are forced to use this.

You can use it this way:
private string[] myProp;
public string[] MyProp
{
get
{
if (myProp == null)
{
myProp = new String[2];
}
return myProp;
}
set
{
myProp = value;
}
}
And it's possible to acces myProp[1] as MyProp[1] for Example

Exposing your array through a read-only property might cover your needs. Since you don't want to allow other code to assign the array as such, there is no need for a public setter:
private string[] myProperty;
public string[] MyProperty
{
get
{
if (myProperty == null)
{
myProperty = new String[2];
}
return myProperty;
}
}
Then you can write code as such:
theObject.MyProperty[1] = "some string";
...but you cannot replace the array itself:
theObject.MyProperty = new string[2]; // will not compile

An option is to recode it as follows:
private string[] myProperty = new string[2];
public string[] MyProperty
{
get
{
return myProperty;
}
set
{
myProperty = value;
}
}
It'll compile, but it does have its own set of issues (fxCop will yell about it, but it can lead you to other options).

You could do something like this:
class Indexers
{
private string[] _strings = new [] {"A","B"};
private int[] _ints = new[] { 1, 2 };
public string[] Strings
{
get{ return _strings;}
}
public int[] Ints
{
get{ return _ints;}
}
}
class Program
{
static void Main(string[] args)
{
Indexers indexers = new Indexers();
int a1 = indexers.Ints[0];
string a2 = indexers.Strings[0];
}
}

C# provides no built-in mechanism to create indexed properties. You can use a class-level indexer (using this[int index] notation), but nothing like this on a property level.
One option is to create a helper class with an indexer and use this class as the property type. See an example on MSDN.

First, in-field declaration avoids excess check:
private string[] myProperty = new string[2];
You can implement several indexers via overloading by input type:
public string this[int index]
{
get
{
return myProperty[index];
}
set
{
myProperty[index] = value;
}
}
public object this[object a, object b] // different input type(s) (and different return type)
{
get
{
// do other stuff
}
}

You need to use an indexer. It works a little differently. See example:
public class Node
{
public Node this[int offset]
{
get { return localList[offset]; }
}
}
Note: You are allowed only one indexer per class. The reason is that it is too confusing to the compiler as to the meaning, so you only are allowed one.
You can also do this:
private static int[] _widget = new int[Counter];
public static int [] Widget
{
get { return _widget; }
set { _widget = value; }
}
...
for (int i = 0; i < MyClass.Counter; i++)
{
MyClass.Widget[i] = i;
}
...
double _newWidget5 = MyClass.Widget[5];
// and so on...

Related

The type name ____ does not exist in the type ____

I know the question is already out there. But i cant solve my problem with the other solutions. I want to create a List out of Lists.
My Code:
class SomeClassName
{
static List<char> saveFields = new List<char>();
public static List<char> SaveFields
{
get { return saveFields; }
set { saveFields = value; }
}
}
public void someMethod
{
List<SomeClassName.SaveFields> someListName = new List<SomeClassName.SaveFields>();
}
My Namespace is TicTacToe so there is no name issue.
How can i solve this error?
I get the error for "SaveFields"
SomeClassName.SaveFields isn't a type, it is a property. The type of that property is List<char>. If you want to create a variable with the same type, you have to use List<char>.
You can assign that value to the variable though:
public void someMethod()
{
List<char> someListName = SomeClassName.SaveFields;
}
Have you tried using generics?
class SomeClassName
{
static List<T> saveFields = new List<T>();
public static List<T> SaveFields
{
get { return saveFields; }
set { saveFields = value; }
}
}
It is insanely good, useful but machine resource hunger, use carefully

I want to use `[]` to check if a string exists in an array or not

Currently my code is like that
public class ExampleClass
{
private static string[] words = new string[] { "Word1","Word2","Word3","Word4","Word5" };
public static bool IsExist(string Word)
{
return words.Any(w => w == Word);
}
}
And am calling that as
ExampleClass.IsExist("Word1"); //Returns true
ExampleClass.IsExist("WordNotExist"); //Returns false
But i want to call like this
ExampleClass.IsExist["Word1"]; //Returns true
ExampleClass.IsExist["WordNotExist"]; //Returns false
How should i modify my class to do so please help me out
I think you are going really bad here since using an indexer to call a method is just wrong. And with that, you can't have indexers on static classes.
That said, this is how it does work:
public class ExampleClass
{
public class IsExistHelper
{
private static string[] words = new string[] { "Word1", "Word2", "Word3", "Word4", "Word5" };
public bool this[string Word]
{
get
{
return words.Any(w => w == Word);
}
}
}
public static IsExistHelper IsExist { get; } = new IsExistHelper();
}
I have used an inner class to create a helper, which creates your property name. Inside there is an indexer that has your original code.
Not sure why you would want to do it that way, but:
public class ExampleClass
{
private string[] words = new string[] { "Word1", "Word2", "Word3", "Word4", "Word5" };
public bool this[string Word]
{
get { return words.Any(w => w == Word); }
}
}
It must be called with an instance:
var _ = new ExampleClass();
var isTrue = _["Word1"] == true
Unfortunately you cannot do it with a static member. Alternatively you need to create an indexer inside an auxillary class that's instance name is IsExist.
My opinion is that you should leave it as it is.
To achieve it exactly the way you want it (even though in my opinion it isn't a good design) use an inner class that will override the [] operator and will check your condition. Then in your original class have a property of that inner class.
Keep in mind that when overriding the [] operator you can't be using a static class.
See that instead of using Any you can just use Contains - because you are checking for the entire object itself it is a cleaner way to do so
public static class ExampleClass
{
public class InnerIsExist
{
private string[] words = new string[] { "Word1", "Word2", "Word3", "Word4", "Word5" };
public bool this[string word]
{
get { return words.Contains(word); }
}
}
public static InnerIsExist IsExist { get; } = new IsExistClass();
}
Use:
var doesItContain = ExampleClass.IsExist["b"]; // false
Currently, you are calling a function and its as simple as declaring it, but for square brackets, you will have to overload them. Here is a helpful link: How do I overload the square-bracket operator in C#?
Basically, in your case it should look like this:
public bool this[string Word]
{
get { return words.Any(w => w==Word); }
}
I haven't tested the code, so let me know if it works.

Implementing a string array property of an Interface type

So in my interface I have written this:
public interface IFileExport
{
string[] FileHeaders { get; set; }
}
And in my class something like this:
public class AdditionsFileExport: IFileExport
{
public string[] FileHeaders {
get
{
return new string["wwwe", "sdd", "e3rs"];
}
set { FileHeaders = value; } }
}
But I get two errors:
Cannot implicitly convert type string to int. (On the GET
section)
Function is recursive on all path. (On the SET section)
What are the wrong things I have done and what is the correct way?
Your declaration or array is syntactically incorrect.
public class AdditionsFileExport: IFileExport
{
// "wwwe", "sdd", "e3rs" will be default values
private string[] fileHeaders = new[] { "wwwe", "sdd", "e3rs" };
public string[] FileHeaders
{
get { return fileHeaders; }
set { fileHeaders = value; }
}
}
If you need readonly property, remove setter and declare fileHeaders with readonly keyword.
Note, that this:
public class AdditionsFileExport: IFileExport
{
public string[] FileHeaders
{
get { return new[] { "wwwe", "sdd", "e3rs" }; }
}
}
isn't a way to go, because every time you call FileHeaders, you create new instance of array. Thus, this assertion will fail:
var foo = new AdditionsFileExport();
Debug.Assert(foo.FileHeaders == foo.FileHeaders);
Also note, that array isn't a good return type in general, because you can't change property implementation, e.g., this way:
public class AdditionsFileExport: IFileExport
{
private readonly fileHeaders = new List<string>
{
"wwwe", "sdd", "e3rs"
};
public string[] FileHeaders
{
// won't compile, because List<> isn't array
get { return fileHeaders; }
}
}
IEnumerable<string> would be a better choise here.

C# Controlling access to an array property element

I would like to bring access to an internal array with a Property, but controlling the access to array elements.
I have write a simple example that can explain my problem better than myself.
In the example, I provide a 'Fail' class and a 'Controlled' class. The second one runs as I would like, but the approach is a bit different and it is usefull only with one array.
My question is the next:
What about if I must to have two different arrays and therefore two differenct properties.
How to do it ?
Thanks.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("The Fail Class:");
MyFailClass MyFailTestClass = new MyFailClass(5);
MyFailTestClass.MyList[2] = 11;
if (MyFailTestClass.Modified) {
Console.WriteLine("Right");
} else {
Console.WriteLine("Error");
}
Console.WriteLine("The Controlled Class:");
MyControlledClass MyControlledTestClass = new MyControlledClass(5);
MyControlledTestClass[2] = 11;
if (MyControlledTestClass.Modified) {
Console.WriteLine("Right");
} else {
Console.WriteLine("Error");
}
Console.ReadKey();
}
}
public class MyFailClass
{
// Property
public byte[] MyList
{
get
{
return myList;
}
set // <--------- Never enters here if I set a concrete array element
{
Modified = !myList.Equals(value);
myList = value;
}
}
public bool Modified { get; set; }
// Constructor
public MyFailClass(int elements)
{
myList = new byte[elements];
}
private byte[] myList;
}
public class MyControlledClass
{
// Property
public byte this[int index]
{
get
{
return myList[index];
}
set
{
Modified = !myList[index].Equals(value);
myList[index] = value;
}
}
public bool Modified { get; set; }
// Constructor
public MyControlledClass(int elements)
{
myList = new byte[elements];
}
private byte[] myList;
}
}
You might consider replacing your array property by, say, an ObservableCollection<T>.
You would probably expose the property as IList<T> since the fact that it's observable is an internal implementation detail.
public class MyClass
{
public IList<byte> MyList
{
get { return _myList; }
}
private IList<byte> _myList = new ObservableCollection<byte>();
...
}
The implementation of MyClass should handle _myList's PropertyChanged and CollectionChanged events.
Note you don't generally need a setter for a collection property - if the caller wants to replace the list he can call:
myClass.MyList.Clear();
then add new elements.
If you want two arrays, it stands to reason that you might later want three, or four (I don't know for sure, but that seems to be how things go).
In this case, I would consider making a class that's an aggregate of your "MyControlledClass"
public class IndexedClass
{
// Property
public byte this[int index]
{
get
{
return myList[index];
}
set
{
Modified = !myList[index].Equals(value);
myList[index] = value;
}
}
}
public class IndexedClassGroup
{
// Property
public IndexedClass this[int index]
{
get
{
return myList[index];
}
set
{
Modified = !myList[index].Equals(value);
myList[index] = value;
}
}
}
Then, you could access these things like a two dimensional array.
Personally, I'm a little leery of exposing an array as a gettable/settable concept, in theory, so I don't know a whole lot about the ins and outs of doing that. Whether a classes uses an array or a list or whatever seems like a private implementation detail rather than a public property. If you're going to expose something, expose an ICollection<> or IEnumerable<> and resolve it internally to an array. My two cents, anyway.

Assigning fields dynamically

I have set of properties as follows:
public string Foo1 {set;get;}
public string Foo2 {set;get;}
public string Foo3 {set;get;}
public string Foo4 {set;get;}
public string Foo5 {set;get;}
public string Foo6 {set;get;}
public string Foo7 {set;get;}
public string Foo8 {set;get;}
public string Foo9 {set;get;}
......
public string Foo50 {set;get;}
then i m iterating through a collection as follows:
foreach(var element in sortedCollection.Keys){
if(element != null)
// in this block I would like to assign the element to the properties above
// ex:
foo?? = sortedCollection[element];
// ?? need to be replaced by index.
}
Is there an easy way to do this?
I think a better design would be:
public List<string> Foos { get; private set; }
If you can't change it, you could probably do something like:
var type = typeof(MyCalss);
int index = 1;
foreach (var key in sortedCollection.Keys)
{
var value = sortedCollection[key];
var prop = type.GetProperty("Foo" + index);
if (prop != null) prop.SetValue(this, value, null);
index++;
}
... of course with some error handling, and where this assumes this is a method within your class. Can you determine an index based on the values in your sortedCollection?
you can use reflection and do it in a loop:
for ( int i = 1 ; i < 51 ; i++)
this.GetType().GetProperty(string.Format("Foo{0}",i)).SetValue(this,desiredValue,null);
but i think i'll recommend using indexers
http://msdn.microsoft.com/en-us/library/2549tw02%28v=vs.80%29.aspx
You can do what you want by:
Using a for loop instead of foreach. This way you can operate with the current index.
Using reflections. You can get a list of properties for your class and access them dynamically. For example, see Type.GetProperties.
But why don't you just use a List<string> Foos instead of lots of properties?
You should use reflection.
this.GetType().GetProperty("Foo" + i).SetValue(this, sortedCollection[element], null);
Two things though:
GetProperty's cost is not null. So if you're doing this a lot of times, you might want to store the result of GetProperty in some field and then use this field in your foreach.
If your properties are really named Something1, Something2, etc..., then you may have a design flaw you may want to correct before doing this (replace all you string members with one List).
You need to use reflection (Type.GetProperty()) to get the property and set it's value.
Assuming that the properties are defined in class called MyClass:
foreach(var element in sortedCollection.Keys){
if(element != null)
// in this block I would like to assign the element to the properties above
// ex:
//foo?? = sortedCollection[element];
// not sure how you are getting the index here, may be you need to use for loop
PropertyInfo pi = typeof(MyClass).GetProperty("Foo" + index);
// ?? need to be replaced by index.
if (pi != null)
{
pi.SetValue(<object of MyClass>, sortedCollection[element], null);
}
}
void Main()
{
var foo = new Foo();
foo[1] = "Foo1";
//foo.Dump();
}
public class Foo
{
public string Foo1 {set;get;}
public string Foo2 {set;get;}
public string Foo3 {set;get;}
public string Foo4 {set;get;}
public string Foo5 {set;get;}
public string Foo6 {set;get;}
public string Foo7 {set;get;}
public string Foo8 {set;get;}
public string Foo9 {set;get;}
public string this[int index]
{
get
{
return getPropertyValue(index);
}
set
{
setPropertyValue(index, value);
}
}
private void setPropertyValue(int i, string value)
{
var propi = this.GetType().GetProperty("Foo" + i);
if (propi != null)
propi.SetValue(this,value,null);
}
private string getPropertyValue(int i)
{
var propi = this.GetType().GetProperty("Foo" + i);
if (propi != null)
return (string)propi.GetValue(this, null);
return null;
}
}
I would actually use reflection, or if this is called a lot, make a dynamic method and ILEmit to do it (much faster at runtime than reflection).
However just to suggest something different, you could change the class containing the Foo* properties to have each getter/setter read from an indexed list:
public class FooOfDoom
{
public string[] Foos = new string[2];
public string Foo1
{
set { Foos[0] = value; }
get { return Foos[0]; }
}
public string Foo2
{
set { Foos[1] = value; }
get { return Foos[1]; }
}
}
Then your class doesn't really change, as far as its contract with all the other code, since the properties are still there, but now you can assign right to Foos instead of through each individual property.
Again, in reality I would actually use a DynamicMethod if I was doing it myself.
Personally, I disagree with most of the other posters here. I think the use of reflection should be limited to those situations where it is really called for (object inspection, certain GUI situations, etc). In this case, with just a little more typing, it is possible to write a strongly-typed program and still do what you want. I'll offer two alternatives. Both alternatives will offer the ability to access your properties by name as well as by index.
In the first alternative, I'll assume that we are allowed to change the definition of your properties. In the second alternative, I'll assume that those definitions must remain unchanged.
The first alternative moves the data to a separate array, adds helper methods to access the data by index, and alters the properties to use the helper methods:
private class Version1 {
private readonly string[] underlyingData=new string[50];
public string Foo1 { get { return ReadFoo(1); } set { SetFoo(1, value); } }
public string Foo2 { get { return ReadFoo(2); } set { SetFoo(2, value); } }
public string Foo3 { get { return ReadFoo(3); } set { SetFoo(3, value); } }
//......
public string Foo50 { get { return ReadFoo(50); } set { SetFoo(50, value); } }
private string ReadFoo(int index) {
return underlyingData[index-1]; //1-based indexing
}
private void SetFoo(int index, string value) {
underlyingData[index-1]=value; //1-based indexing
}
}
The second alternative leaves the property definitions unchanged, and two static arrays of delegates representing the reading and writing function of those properties.
private class Version2 {
private static readonly Func<Version2, string>[] readers=new Func<Version2, string>[] {
c => c.Foo1,
c => c.Foo2,
c => c.Foo3,
//......
c => c.Foo50,
};
private static readonly Action<Version2, string>[] writers=new Action<Version2, string>[] {
(c,v) => c.Foo1=v,
(c,v) => c.Foo2=v,
(c,v) => c.Foo3=v,
//......
(c,v) => c.Foo50=v,
};
public string Foo1 { set; get; }
public string Foo2 { set; get; }
public string Foo3 { set; get; }
//......
public string Foo50 { set; get; }
private string ReadFoo(int index) {
return readers[index-1](this); //1-based indexing
}
private void SetFoo(int index, string value) {
writers[index-1](this, value); //1-based indexing
}
}

Categories