Array index returns null instead

I'm currently trying to implement an “indexed” property in 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 follows:

 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 there is a safe index call that results in a null value, without the need for it to wrap it in a try catch again and again.

Another thing that I do not want to use is the class index, because I need several properties that work this way with different types (int, string, bool, custom class, etc.).

(Again, for a simple example, I know that in this case I can say "i <Ids.Length")

+9
source share
8 answers

OK, the whole new approach. Since you have several possible types and you want to use the "joker" method, you can save the values ​​as a collection of keys and values ​​in your class, then such a method will become possible.

First, to keep the values ​​inside:

 public class TestClass { private Dictionary<Type, Array> _values = new Dictionary<Type, Array>(); } 

Now, to populate this 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); } 

Using:

 for (int i = 0; i < 10; i++) { int? id = testClass.Get<int?>(i); string name = testClass.Get<string>(i); //... } 
+2
source

If you are interested in null values ​​that are already null, for example. struct you could get 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 let you just call

 int? id = testClass.Ids.GetValueOrNull(i); 

However, given that you need to support an arbitrary number of types, my suggestion would be to implement a wrapper around the array and take control of how you access the data, for example.

 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 use (or box / unbox when using value types) data for the expected type on the receiving side, for example.

 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 eg MyClass instance = testClass.Instances[i]; } 
+6
source

Here really is not as much as simple:

 if (i >= array.Length) return null; else return array[i]; 

or using an operator ? :

 return (i >= array.Length) ? null : array[i]; 
+1
source

You can use the method instead of the property:

 public int? Ids(int i) { if (i >= 0 && i < _ids.length) { return _ids[i]; } return null; } 
+1
source
  • from what i read, i see that you are executing an array type property but not indexing
  • it's a kind of moveton for faking an out of range index, and it would be much better if you took care of your out of range. at the end of the day, no one is stopping you from setting a default value (in your case NULL) when the range is violated.

if you need a shortcut for your situation 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; } 
0
source

try:

 for (int i = 0; i < Ids.Length; i++) { if (!String.IsNullOrEmpty(testClass.Ids[i].Tostring()) int? id = testClass.Ids[i]; } 
0
source

It seems like you need to use the class index here. Here is a direct answer for your TestClass example.

You can also get your own custom collection class strictly for identifiers, which stores int [] inside and overrides all the corresponding access calls Ie) Add, Delete, etc. (and index the collection like this to make it easier to use). Then you may have a property called Ids in your TestClass that behaves as an 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; } } } 

Using:

  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; } 
0
source

People may start complaining that it might be FirstOrDefault , 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(); } 

Keep in mind that in this case you may need to declare the array as int?[] Otherwise the default value is 0 and not null .

0
source

Source: https://habr.com/ru/post/957488/


All Articles