我的基类中有两个数组,我想创建可以在两个数组中使用的索引器,下面是我想做的MVCE。
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;
}
}
}
在上述代码中,如果您注释掉了private char[] grades = new string[size];
和grades[i] = 'F';
行,则可以将索引器用作object_name[i]
,但我希望能够同时访问namelist
和grades
由索引器组成。
注意:我无法像在应用程序中那样使用结构将它们包装在一起,因此大小可能并不总是相同。
这是否可行,或者我需要解决一些问题。
修改
我正在寻找类似names.namelist[i]
和names.grades[i]
的东西,或者一些我可以分别访问它们的语句。同样,索引器逻辑也不是一致的,甚至在某些数组中大小也有所不同,此处跳过了这些索引,以简化MVCE。
答案 0 :(得分:3)
对不起,不能做
尽管 Indexers 可以 Overloaded ,并且可以具有多个形式参数,但是您不能在相同的 Parameter 的基础上进行2个变化。同班。这是语言限制(或祝福)
Indexers (C# Programming Guide)
但是,这应该使您有几种选择。
从C#7.0开始,C#支持参考返回值(参考 返回)。参考返回值允许方法返回 将变量而不是值的引用返回给调用者。的 然后,调用者可以选择将返回变量视为 按值或引用返回。呼叫者可以创建一个新的 变量本身就是对返回值的引用,称为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, ect.
object.NameList(1) = "bob";
这就是说,您可以创建一个具有索引器所需功能的类,并使它们成为主类的属性。因此,您得到的内容与您设想的object.Namelist[0]
和object.Grades[0]
注意 :在这种情况下,您可以将数组作为引用向下传递,并且仍然可以像您一样在主数组中访问它们
同时包含这两个示例
给出
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;
}
}
课程
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];
}
用法
var bobo = new Bobo();
bobo.Ints[1] = 234;
bobo.DoInts(1) = 42;
答案 1 :(得分:1)
也许是这样的:
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;
}
}
}
答案 2 :(得分:1)
我认为只有两个参数的索引器才能实现您想要的。
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";
}
}