0

Obviously, I'm not looking for the classic:

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

but rather, doing the same with a string:

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

I'm curious as to whether there is some actually existing version of "ArrayByName" which would let me find an array by using a string which is its name. Thanks in advance!

Werty980
  • 19
  • 7
  • `garden` is an object reference, not a name. – Ňɏssa Pøngjǣrdenlarp Jul 11 '20 at 15:15
  • 2
    Are you looking for something like [Dictionary](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2?view=netcore-3.1)? – 大陸北方網友 Jul 11 '20 at 15:17
  • You can create an method and use c# reflection to get property details. If it is a property and then type cast it to an array and access properties – Pavan Kumar Aryasomayajulu Jul 11 '20 at 15:18
  • @ŇɏssaPøngjǣrdenlarp so... there's no way (you know of) to do this? – Werty980 Jul 11 '20 at 15:19
  • as @KyleWang said something like `Dictionary()` or `Dictionary()` but it's not going to be a `cool_NEW` it would be the same (reference) – jjchiw Jul 11 '20 at 15:19
  • so you want to lookup objects based on keys? because garden is just a reference. – HMZ Jul 11 '20 at 15:20
  • @KyleWang honestly, i'm starting to believe so! lists are more versatile, but come with some complications, and arrays are very basic, so you're... right? (i guess) – Werty980 Jul 11 '20 at 15:21
  • @OlivierRogier it is, just not with arrays from what i've heard – Werty980 Jul 11 '20 at 15:23
  • your best bet would be a `Dictionary` with an object for a value or a `KeyValuePair` in the same way – HMZ Jul 11 '20 at 15:25
  • @HMZ yes yes, i'm trying to learn the usage of those "dictionaries" currently. it is by far the best bet. still, i hate how lists and dictionaries force you to add items one-by-one. – Werty980 Jul 11 '20 at 15:27
  • 1
    You can add more than one thing to a list at a time... `AddRange` takes an enumerable.. this sounds like an X/Y question to be honest. You are asking how to do something that you think solves a problem instead of showing what problem you are trying to solve and letting people give you the best solution. – Charleh Jul 11 '20 at 16:01

1 Answers1

1

It is impossible, as I know, and this may cause lots of problems about reflexion and generated IL.

There is the nameof operator and meanings to get variables names in the caller of a method, but it is not intended for your goal.

Perhaps there some reflection tools to do that, but I don't know.

Perhaps you can do that using huge reflexion on a whole assembly by parsing all classes, all instances, all fields and properties members, all methods and all local vars of these methods...

In all case, you may encounter problems with duplicates vocabulary.

But you can use a Dictionary keyed by the name of the intended variable name.

Thus you create a sort of data table.

We use a class variable as private to store some one-dimension string arrays and public methods to add and remove these arrays from the collection as well as a method to find which can match having one string using Contains (or equality if you want).

The collection

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

The register and unbregister methods

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);
  }
}

The find method

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

Test

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));
}

Output

Tulip,Rose
Flower 1,Flower 2,Flower 3

Improvements

You can create a whole class to offer the desired behavior

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));
}

We can also create a generic manager for any type

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

Or simply any object:

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

Also we can manage registering and unregistering several differents names for the same reference and so on... by throwing an exception, returning a bool or do nothing.

Here the code only accept to add a name or a reference only if both is not already in the collection.