Как найти ссылку на массив по имени переменной, как определено в коде в C#? - PullRequest
0 голосов
/ 11 июля 2020

Очевидно, я не ищу classi c:

string[] garden = {"Tulip"};
Console.WriteLine(garden[0]);

, а делаю то же самое со строкой:

string[] garden = {"Tulip"};
string gardenname = "garden";
string[] cool_NEW_array = ArrayByName(gardenname);
Console.WriteLine(cool_NEW_array[0])

Мне любопытно, как о том, существует ли какая-то реально существующая версия "ArrayByName", которая позволила бы мне найти массив, используя строку, которая является его именем. Заранее спасибо!

1 Ответ

1 голос
/ 11 июля 2020

Насколько я знаю, это невозможно, и это может вызвать множество проблем с отражением и сгенерированным IL.

Существует оператор nameof и значения для получения имен переменных в вызывающем методе, но он не предназначен для вашей цели.

Возможно, для этого есть какие-то инструменты отражения, но я не знаю.

анализ всех классов, всех экземпляров, всех полей и членов свойств, всех методов и всех локальных переменных этих методов ...

В любом случае вы можете столкнуться с проблемами с дублированием словаря.

Но вы можете использовать Dictionary с ключом по имени предполагаемого имени переменной.

Таким образом вы создаете своего рода таблицу данных.

Мы используем переменную класса как частную для хранения какой-то одной- массивы строк измерений и методы publi c для добавления и удаления этих массивов из коллекции, а также метод поиска, который может соответствовать одной строке с использованием Contains (или равенства, если вы хотите).

Коллекция

static private readonly Dictionary<string, string[]> RegisteredArrays 
  = new Dictionary<string, string[]>();

Методы регистрации и отмены регистрации

static public void RegisterArray(string name, string[] array)
{
  if ( !RegisteredArrays.ContainsKey(name)
    && !RegisteredArrays.ContainsValue(array) )
    RegisteredArrays.Add(name, array);
}

static public void UnregisterArray(string name)
{
  if ( RegisteredArrays.ContainsKey(name) )
    RegisteredArrays.Remove(name);
}

static public void UnregisterArray(string[] array)
{
  if ( RegisteredArrays.ContainsValue(array) )
  {
    var item = RegisteredArrays.FirstOrDefault(kvp => kvp.Value == array).Key;
    RegisteredArrays.Remove(item);
  }
}

Метод поиска

static public IEnumerable<string[]> FindRegisteredArray(string name)
{
  foreach ( var item in RegisteredArrays )
    if ( item.Key == name )
      yield return item.Value;
}

Тест

static void Test()
{
  string[] garden1 = { "Tulip", "Rose" };
  string[] garden2 = { "Flower 1", "Flower 2", "Flower 3" };

  RegisterArray(nameof(garden1), garden1);
  RegisterArray(nameof(garden2), garden2);

  string gardenname = "garden1";

  foreach ( var array in FindRegisteredArray(gardenname) )
    Console.WriteLine(string.Join(",", array));

  foreach ( var array in FindRegisteredArray("garden2") )
    Console.WriteLine(string.Join(",", array));
}

Вывод

Tulip,Rose
Flower 1,Flower 2,Flower 3

Улучшения

Вы можете создать целый класс, чтобы предложить желаемое поведение

static public class NamedStringArrayManager
{
  static private readonly Dictionary<string, string[]> RegisteredArrays
    = new Dictionary<string, string[]>();

  static public void Register(string name, string[] array)
  {
    if ( !RegisteredArrays.ContainsKey(name)
      && !RegisteredArrays.ContainsValue(array) )
      RegisteredArrays.Add(name, array);
  }

  static public void Unregister(string name)
  {
    if ( RegisteredArrays.ContainsKey(name) )
      RegisteredArrays.Remove(name);
  }

  static public void Unregister(string[] array)
  {
    if ( RegisteredArrays.ContainsValue(array) )
    {
      var item = RegisteredArrays.FirstOrDefault(kvp => kvp.Value == array).Key;
      RegisteredArrays.Remove(item);
    }
  }

  static public IEnumerable<string[]> Find(string name)
  {
    foreach ( var item in RegisteredArrays )
      if ( item.Key == name )
        yield return item.Value;
  }
}
static void Test()
{
  string[] garden1 = { "Tulip", "Rose" };
  string[] garden2 = { "Flower 1", "Flower 2", "Flower 3" };

  NamedStringArrayManager.Register(nameof(garden1), garden1);
  NamedStringArrayManager.Register(nameof(garden2), garden2);

  string gardenname = "garden1";

  foreach ( var array in NamedStringArrayManager.Find(gardenname) )
    Console.WriteLine(string.Join(",", array));

  foreach ( var array in NamedStringArrayManager.Find("garden2") )
    Console.WriteLine(string.Join(",", array));
}

Мы также можем создать общий c менеджер для любого типа

static public class NamedInstanceManager<T>
{
  static private readonly Dictionary<string, T> RegisteredArrays
    = new Dictionary<string, T>();

  static public void Register(string name, T instance)
  {
    if ( !RegisteredArrays.ContainsKey(name)
      && !RegisteredArrays.ContainsValue(instance) )
      RegisteredArrays.Add(name, instance);
  }

  static public void Unregister(string name)
  {
    if ( RegisteredArrays.ContainsKey(name) )
      RegisteredArrays.Remove(name);
  }

  static public void Unregister(T instance)
  {
    if ( RegisteredArrays.ContainsValue(instance) )
    {
      var item = RegisteredArrays.FirstOrDefault(kvp => kvp.Value.Equals(instance)).Key;
      RegisteredArrays.Remove(item);
    }
  }

  static public IEnumerable<T> Find(string name)
  {
    foreach ( var item in RegisteredArrays )
      if ( item.Key == name )
        yield return item.Value;
  }
}

Или просто любой объект:

static public class NamedInstanceManager
{
  static private readonly Dictionary<string, object> RegisteredArrays
    = new Dictionary<string, object>();

  static public void Register(string name, object instance)
  {
    if ( !RegisteredArrays.ContainsKey(name)
      && !RegisteredArrays.ContainsValue(instance) )
      RegisteredArrays.Add(name, instance);
  }

  static public void Unregister(string name)
  {
    if ( RegisteredArrays.ContainsKey(name) )
      RegisteredArrays.Remove(name);
  }

  static public void Unregister(object instance)
  {
    if ( RegisteredArrays.ContainsValue(instance) )
    {
      var item = RegisteredArrays.FirstOrDefault(kvp => kvp.Value.Equals(instance)).Key;
      RegisteredArrays.Remove(item);
    }
  }

  static public IEnumerable<object> Find(string name)
  {
    foreach ( var item in RegisteredArrays )
      if ( item.Key == name )
        yield return item.Value;
  }
}

Также мы можем управлять регистрацией и отменой регистрации нескольких разных имен для одной и той же ссылки и так далее .. .бросив исключение, вернув логическое значение или ничего не сделав.

Здесь код принимает только добавление имени или ссылки только в том случае, если и того, и другого еще нет в коллекции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...