Reputation: 19
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!
Upvotes: 0
Views: 408
Reputation:
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.
Upvotes: 1