customized array with default value in C# - c#

I'm trying to costruct a custimzed array - which has some properties - and which has two possibilites.
The first when I DO NOT add index, then return a a specified value, something like this:
// in this case I would like to return the 0 index item
Debug.Print(spca)
but in this case:
// in this case it will return the 1 index item fo the array
Debug.Print(spca[1])
and in this case:
//will return the 2 index item fo the array
Debug.Print(spca[2])
So the concept is if I would like to reach the 0 index item, it can be done without index input.

Can not be done using only an array. You'd need to create your own class and an indexer property public ... this[int index].
However, the requirement of using the first value if no index is given can not be solved, as this would be equal to "not calling a method", which can not be done.
Based on the comments by crashmstr you could try the following (I currently cant test it, but you should get it to work):
public class SpecialArray
{
private int[] m_theArray;
public SpecialArray(int size)
{
m_theArray = new int[size];
}
public int this[int index]
{
get { return m_theArray[index]; }
set { m_theArray[index] = value; }
}
// Please note that this override is NOT INTUITIVE TO THE USER
// Who would expect that the string representation of the array
// might be the string representation of its first element?
public override string ToString()
{
return m_theArray[0].ToString();
}
public static implicit operator int(SpecialArray a)
{
return m_theArray[0];
}
}
With this class, the following should work:
SpecialArray arr = new SpecialArray(5);
arr[0] = 10;
arr[1] = 9;
arr[2] = 8;
arr[3] = 7;
arr[4] = 6;
int elemZero = arr; // equal to arr[0]
int elemOne = arr[1];
...

using System;
using System.Collections.Generic;
using System.Windows.Forms;
public class spca
{
public static void Main(string[] args)
{
var spacs = new spca();
spacs[0] = "t";
spacs[1] = "tt";
spacs[1] = "ttt";
// this will call the overritten Tostring and deliver first value
Console.WriteLine(spacs);
Console.WriteLine(spacs[1]);
Console.WriteLine(spacs[2]);
}
private Dictionary<int, string> _innerDictionary = new Dictionary<int, string>();
public override string ToString()
{
return _innerDictionary[0];
}
public object this[int key]
{
get
{
if (_innerDictionary.ContainsKey(key)) return _innerDictionary[key];
return null;
}
set
{
_innerDictionary[key] = (string)value;
}
}
}

Related

When using GetPosition for ArrayAdapter, Object with Equal Fields Return UnEqual

I have created a dropdown in Android Xamarin from which I would like to auto select a dropdown value on page load. When the page is launched, it is passed a MyClass object with a Num value of 52. My dropdown has been passed an ArrayAdapter which has a list of MyClass objects, one of which has a Num value of 52. When I try to mySpinner.SetSelection(recommendedPosition); it is not working because myClassAdapter.GetPosition(recommendedValue) returns -1
I thought that the example in the following article (which shows me how to override the Equals and Hash functions of MyClass) would help me, but it still results in -1 being returned. It seems that these overridden functions are not being hit when I place a breakpoint on them.. but I understood that the GetPosition method calls IndexOf which should result in my overriden functions being called.
https://www.javaworld.com/article/3305792/comparing-java-objects-with-equals-and-hashcode.html
In this example, MyClass has one field of Num.. but my code has many more properties in MyClass, all of which are equal between recommendedValue and one of the items in listMyClass.
In InstantiateItem of my ViewPager I call:
var recommendedValue = new MyClass("52");
var List<MyClass> listMyClass = new List<MyClass> { new MyClass("52"), new MyClass("46") };
mySpinner = view.FindViewById<Spinner>(Resource.Id.mySpinner);
var myClassAdapter = new MyClassAdapter(view.Context, listMyClass);
mySpinner.Adapter = myClassAdapter;
//*
// I need the following to not return -1
//*
var recommendedPosition = myClassAdapter.GetPosition((MyClass)recommendedValue);
MyClass.cs
public class MyClass: Java.Lang.Object
{
private string Num { get; set; } = "";
public MyClass() {}
public MyClass(int? num)
{
Num = String.IsNullOrEmpty(num) ? "" : num;
}
public string GetNum()
{
return Num;
}
public override bool Equals(object other)
{
return Equals(other as MyClass);
}
public bool Equals(MyClass otherItem)
{
if (otherItem == null)
{
return false;
}
return otherItem.Num == Num;
}
public override int GetHashCode()
{
int hash = 19;
hash = hash * 31 + (Num == null ? 0 : Num.GetHashCode());
return hash;
}
}
Maybe you could consider not using GetPosition method,you could directly get the position like this :
var recommendedValue = new MyClass("52");
var List<MyClass> listMyClass = new List<MyClass> { new MyClass("52"), new MyClass("46") };
var recommendedPosition = listMyClass.IndexOf(recommendedValue);
or you could define a GetSelectPosition(MyClass myClass) in your MyClassAdapter :
class MyClassAdapter: ArrayAdapter<MyClass >
{
public Context context;
public List<MyClass> list;
...
public int GetSelectPosition(MyClass myClass)
{
return list.IndexOf(myClass);
}
}
then you could call like :
var recommendedPosition = myClassAdapter.GetSelectPosition(recommendedValue);

How do I approach array properties when I need an array to have an interval in C#?

I am extremely new to C# and am still trying to wrap my head around some of its core concepts.First time posting a question to StackOverflow.
So this is what I need help with:
Make a property for: private string array; : so that:
"Each element of an array needs to be >=0 and <=10"
Should I run it through for, and then set array=value for each element or what?
This is what I did:
private string array;
public int[] Array
{
get { return array; } //-is this part good for the task?
set
{
//what do I do here to make sure the elements are withing the
//given interval?
}
}
See if this is what you need (Demo):
public class myClass
{
private int[] _Array = new int[10];
public int this[int index]
{
get { return _Array[index]; }
set
{
if (value >= 0 && value <= 10)
_Array[index] = value;
}
}
}
public class Program
{
public static void Main(string[] args)
{
myClass m = new myClass();
m[0] = 1;
m[1] = 12;
Console.WriteLine(m[0]); // outputs 1
Console.WriteLine(m[1]); // outputs default value 0
}
}
You are looking for something like this
private int[] _privateArray;
public int[] PublicArray
{
get
{
return _privateArray;
}
set
{
foreach (int val in value)
{
if (val < 0 || val > 10) throw new ArgumentOutOfRangeException();
}
// if you get to here you can set value
_privateArray = (int[])value.Clone();
}
}
please note private property and public property must be same type

Using Indexers for multiple Arrays in the class c#

I have two arrays in my Base class, and I want to create Indexers that can be used in both of them, attached below is an MVCE of what I am trying to do.
class Indexer
{
private string[] namelist = new string[size];
private char[] grades = new string[size];
static public int size = 10;
public IndexedNames() {
for (int i = 0; i < size; i++){
namelist[i] = "N. A.";
grades[i] = 'F';
}
}
public string this[int index] {
get {
string tmp;
if( index >= 0 && index <= size-1 ) {
tmp = namelist[index];
} else {
tmp = "";
}
return ( tmp );
}
set {
if( index >= 0 && index <= size-1 ) {
namelist[index] = value;
}
}
}
In the above coed if you comment out the lines private char[] grades = new string[size]; and grades[i] = 'F'; then you can use the indexers as object_name[i] but I want to be able to access both namelist and grades by indexers.
Note : I cannot use structures to wrap them together as in my application, there size may not always be same.
Is this possible or I would need to go around with some hack.
Edit
I am looking for something like names.namelist[i] and names.grades[i], or some statements that I can access them separately. Also Indexer logic is not consistent, and even size varies in some arrays, that was skipped here to aid simplicity in MVCE.
Sorry, no-can-do.
Although Indexers can be Overloaded and can have more than one formal parameter, you can't make two variations based on the same Parameter in the same class. This is a Language Limitation (or blessing).
Indexers (C# Programming Guide)
However, this should lead you to several options.
You can just make use of C#7. Ref returns
Starting with C# 7.0, C# supports reference return values (ref
returns). A reference return value allows a method to return a
reference to a variable, rather than a value, back to a caller. The
caller can then choose to treat the returned variable as if it were
returned by value or by reference. The caller can create a new
variable that is itself a reference to the returned value, called a
ref local.
public ref string Namelist(int position)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
if (position < 0 || position >= array.Length)
throw new ArgumentOutOfRangeException(nameof(position));
return ref array[position];
}
...
// Which allows you to do funky things like this, etc.
object.NameList(1) = "bob";
You could make sub/nested classes with indexers
That's to say, you could create a class that has the features you need with indexers, and make them properties of the main class. So you get something like you envisaged object.Namelist[0] and object.Grades[0].
Note : in this situation you could pass the arrays down as references and still access them in the main array like you do.
Example which includes both:
Given
public class GenericIndexer<T>
{
private T[] _array;
public GenericIndexer(T[] array)
{
_array = array;
}
public T this[int i]
{
get => _array[i];
set => _array[i] = value;
}
}
Class
public class Bobo
{
private int[] _ints = { 2, 3, 4, 5, 5 };
private string[] _strings = { "asd","asdd","sdf" };
public Bobo()
{
Strings = new GenericIndexer<string>(_strings);
Ints = new GenericIndexer<int>(_ints);
}
public GenericIndexer<string> Strings ;
public GenericIndexer<int> Ints ;
public void Test()
{
_ints[0] = 234;
}
public ref int DoInts(int pos) => ref _ints[pos];
public ref string DoStrings(int pos) => ref _strings[pos];
}
Usage:
var bobo = new Bobo();
bobo.Ints[1] = 234;
bobo.DoInts(1) = 42;
I think only a two parameter indexer can achieve what you want.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace ConsoleApp1
{
class MyClass
{
protected static Dictionary<string, FieldInfo[]> table = new Dictionary<string, FieldInfo[]>();
static public int size = 10;
protected char[] grades = new char[size];
public object this[string name, int index]
{
get
{
var fieldInfos = table[this.GetType().FullName];
return ((Array)fieldInfos.First((x) => x.Name == name).GetValue(this)).GetValue(index);
}
set
{
var fieldInfos = table[this.GetType().FullName];
((Array)fieldInfos.First((x) => x.Name == name).GetValue(this)).SetValue(value, index);
}
}
static void Main()
{
var names = new MyChildClass();
names[DataColumns.Grades, 1] = 'S';
names[DataColumns.NameList, 9] = "W.S";
}
}
class MyChildClass : MyClass
{
private string[] namelist = new string[size];
static MyChildClass()
{
var t = typeof(MyChildClass);
table.Add(t.FullName, t.GetFields(BindingFlags.NonPublic | BindingFlags.Instance));
}
public MyChildClass()
{
for (int i = 0; i < size; i++)
{
namelist[i] = "N. A.";
grades[i] = 'F';
}
}
}
static class DataColumns
{
public static string NameList = "namelist";
public static string Grades = "grades";
}
}
Maybe something like this:
class Indexer
{
private string[] namelist = new string[size];
private string[] grades = new string[size + 1]; // size +1 to indicate different
// size
static public int size = 10;
public void IndexedNames()
{
for (int i = 0; i < size; i++)
{
namelist[i] = "N. A.";
grades[i] = "F";
}
}
public string this[int i, int j]
{
get
{
string tmp;
// we need to return first array
if (i > 0)
{
tmp = namelist[i];
}
else
{
tmp = grades[i];
}
return (tmp);
}
set
{
if (i > 0)
{
namelist[i] = value;
}
else grades[i] = value;
}
}
}

Array index return null instead of out of bound

I am currently trying to implement an "indexed" property within my class definition.
For example I have the following class:
public class TestClass
{
private int[] ids = null;
public string Name { get; set; }
public string Description { get; set; }
public int[] Ids {
get
{
//Do some magic and return an array of ints
//(count = 5 - in this example in real its not fixed)
return _ids;
}
}
}
Now I like to use this class as the following:
private void DoSomething()
{
var testClass = GetSomeTestClass();
//work with the ids
for (int i = 0; i < 10; i++) //I know I could say i < Ids.Length, its just an example
{
int? id = testClass.Ids[i];
//this will result, in a out of bound exception when i reaches 5 but I wish for it to return a null like a "safe" index call ?!?
}
}
So is there a safe index call that results in a null, without the need for me to wrap it again and again in a try catch.
Another thing I dont wish to use the class index, because I need several properties that work like this, with different types (int, string, bool, custom class and so on).
(Again the for is just a simple example, I know I could in this case say "i < Ids.Length")
If you were only interested in already non-nullable type data e.g. struct you could have gotten away with a simple extension method e.g.
public static class ArrayExt
{
public static Nullable<T> GetValueOrNull(this T[] array, int index) where T: struct
{
return array.Length < index ? new Nullable<T>(array[index]) : null;
}
}
which would have allowed you to simply call
int? id = testClass.Ids.GetValueOrNull(i);
However, given you need to support an arbitrary number of types my suggestion would be to implement a wrapper around an array and take control over how you access the data e.g.
public class SafeArray<T>
{
private T[] items;
public SafeArray(int capacity)
{
items = new T[capacity];
}
public object this[int index]
{
get
{
return index < items.Length ? (object)items[index] : null;
}
set
{
items[index] = (T)value;
}
}
}
public class TestClass
{
public TestClass()
{
Ids = new SafeArray<int>(5);
Instances = new SafeArray<MyClass>(5);
}
...
public SafeArray<int> Ids { get; private set; }
public SafeArray<MyClass> Instances { get; private set; }
}
The key to this approach is to use object as the return type. This allows you to cast (or box/unbox if using value types) the data to the expected type on the receiving end e.g.
for (int i = 0; i < 10; i++)
{
// we need an explicit cast to un-box value types
var id = (int?)testClass.Ids[i];
// any class is already of type object so we don't need a cast
// however, if we want to cast to original type we can use explicit variable declarations e.g.
MyClass instance = testClass.Instances[i];
}
OK, whole new approach. Since you have several possible types and want a "joker" method, you can store the values as key/value collection in your class then such method becomes possible.
First, to store the values internally:
public class TestClass
{
private Dictionary<Type, Array> _values = new Dictionary<Type, Array>();
}
Now to populate that collection with actual data:
_values.Add(typeof(int?), new int[] { 1, 2, 3 });
_values.Add(typeof(string), new string[] { "a", "b", "c", "d", "e" });
And finally the joker method:
public T Get<T>(int index)
{
Type type = typeof(T);
Array array;
if (_values.TryGetValue(type, out array))
{
if (index >= 0 && index < array.Length)
{
return (T)array.GetValue(index);
}
}
return default(T);
}
Usage:
for (int i = 0; i < 10; i++)
{
int? id = testClass.Get<int?>(i);
string name = testClass.Get<string>(i);
//...
}
There's really not much else you can do here than just:
if (i >= array.Length) return null;
else return array[i];
or, using the ? operator:
return (i >= array.Length) ? null : array[i];
You could use method instead of property:
public int? Ids(int i) {
if (i >= 0 && i < _ids.length)
{
return _ids[i];
}
return null;
}
from what I have read I see you are implemet a property of an array type, but not an indexer
it is kind of a moveton to fake index out of range situation and it would be still much much better if you take in your code care about out of range. at the end of the day nobody prevent you on assigning a default (in your case NULL) value when range is violated
if you need a shortcut for your the situation you have described above, I would go for the following method in your class:
public int? ReadAtOrNull(int index)
{
return index < ids.Lenght && index > 0 ? (int?)ids[index] : null;
}
People may start complaining that this may be an overhead, but what if you used Skip and FirstOrDefault?
for (int i = 0; i < 10; i++) //I know I could say i < Ids.Length, its just an example
{
int? id = testClass.Ids.Skip(i).FirstOrDefault();
}
Mind you that in this case you may need to declare your array as int?[] otherwise the default value is 0 instead of null.
please Try :
for (int i = 0; i < Ids.Length; i++)
{
if (!String.IsNullOrEmpty(testClass.Ids[i].Tostring())
int? id = testClass.Ids[i];
}
It seems like the think to do here is to use a class index. Here is a direct answer for your TestClass example.
You could also derive your own custom collection class strictly for Ids that stores an int[] internally and overrides all the appropriate access calls I.e) Add, Remove, etc.. (and index the collection like this to make using it easier). Then you could have a property named Ids in your TestClass that behaves like the example.
I know this question is 3 months old but I hope this still helps.
public class TestClass {
private int[] ids = new int[] { 1, 2, 3, 4, 5 };
public string Name { get; set; }
public string Description { get; set; }
public int? this[int index] {
get {
if (index < 0 || index > ids.Length - 1)
return null;
return ids[index];
}
set {
if (value == null)
throw new ArgumentNullException(
"this[index]",
"Ids are not nullable"
);
ids[index] = (int)value;
}
}
}
Usage:
private void DoSomething() {
TestClass testClass = new TestClass();
for (int i = 0; i < 10; i++) {
int? id = testClass[i];
}
// You can assign to the Ids as well
testClass[0] = 6;
}

how to declare a free length 2d array in c#

Good day,
Normally I create 2D array as follow :
string [,] arr = new string [9,4];
This is a 2D array with 9 rows and 4 columns.
I would like to ask, how to create 2D array with any length.
For example, that is not nessecary to set the row to 9, it can be any number, depends on the situation.
what about simple List<List<T>> ?
This is like a concept, you naturally can wrap up this in your custom class, so consumer of your API don't see these wiered nested declarations.
public class Matrix {
private mtx = new List<List<T>>();
public void Append(T value) {
.....
}
public void InsertAt(T value, int row, int column) {
....
}
}
For that you must be using a List<List<string>> instance. Now you can dynamically add anything you want, however this also has the disadvantage over the array format that you need to check for yourself if you have reached the maximum number of rows or columns.
This Matrix class is space (based on access pattern) and performance efficient:
class Matrix<T>
{
readonly Dictionary<int, Dictionary<int, T>> _rows = new Dictionary<int, Dictionary<int, T>>();
public T this[int i, int j]
{
get
{
var row = ExpandOrGet(j);
if (!row.ContainsKey(i)) row[i] = default(T);
UpdateSize(i, j);
return row[i];
}
set
{
ExpandOrGet(j);
_rows[j][i] = value;
UpdateSize(i, j);
}
}
void UpdateSize(int i, int j)
{
if (j > SizeRows) SizeRows = j;
if (i > SizeColums) SizeColums = i;
}
public int SizeRows { get; private set; }
public int SizeColums { get; private set; }
Dictionary<int, T> ExpandOrGet(int j)
{
Dictionary<int, T> result = null;
if (!_rows.ContainsKey(j))
{
result = new Dictionary<int, T>();
_rows[j] = result;
}
else result = _rows[j];
return result;
}
}
Although you can add further utilities to facilitate your workflow.

Categories