Не выходит получить значение словаря по ключу из метода другого класса

Нужно обратится из класса Print к полю XmlData класса Program, которое является словарём.

Я знаю, что могу обратится к существующему полю используя оператор квадратные скобки. Например, wiwsId = XmlData[WiwId]

Однако, когда я из класса Print обращаюсь к Program.XmlData[A], то получаю ошибку Compiler Error CS0103: Имя "A" не существует в текущем контексте.

Код:

using System.Collections.Generic;

class Program { 
    static readonly string A;
    static readonly string B;

    public static Dictionary<string, string> Data = new(2)
    {
        { A, "TestA" },
        { B, "TestB" }
    };
} 

class Print {
    static void PrintConsole(string[] args) {
        Console.WriteLine(Program.Data[A]);
    }
}

Ответы (1 шт):

Автор решения: KuzCode

Словарь в C# ( Dictionary<TKey, TValue> ) - это объект, который хранит в себе ключи и их значения. Ключ, как и значение, представляет собой экземпляр некоторого класса, в вашем случае, и то, и то - строки.

Поиск значения в словаре работает примерно так:

  1. Вы передаёте в квадратных скобках объект-ключ
  2. Словарь, используя заданный сравниватель ( Comparer<T> ), ищет первый попавшийся объект-ключ, который будет равнятся тому объекту-ключу, что вы передали в квадратных скобках. По умолчанию равными считаются те объекты, у которых совподают их хеши (хеш можно получить для любого объекта так: obj.GetHashCode() ).
  3. После совпадения ключа, словарь берёт то значение, к которому "привязан" ключ, и возращает его вам. Если объект-ключ не совпал ни с одним из тех, что есть в словаре, вы увидите исключение

Зная эту информацию переосмыслим ваш код (который надо прикладывать сразу!!!).

Вы в классе Program сходу определили две строки:

static readonly string A;
static readonly string B;

Строки в C# хранят в себе текст. Их название никак не влияет на то, какой текст в них лежит. Так как вы не присвоили строкам никакой текст, по умолчанию строки стали равны null.

После этого вы создаёте словарь:

public static Dictionary<string, string> Data = new(2)
{
    { A, "TestA" },
    { B, "TestB" }
};

Это абсолютно тоже самое, что если бы вы написали так:

public static Dictionary<string, string> Data = new()
{
    { null, "TestA" },
    { null, "TestB" }
};

Это, очевидно, является абсурдом и выдаст вам исключение времени исполнения (Runtime Error), так как словарь не позволяет ключам равнятся null.

Теперь разберёмся с ошибкой компиляции (Compile Error), описанной в вопросе, в этой строке кода:

Console.WriteLine(Program.Data[A]); // Compiler Error CS0103

Если прочесть описание ошибки, которое вы не приложили (но его всёравно можно найти по коду на MSDN), то можно узнать, что причина ошибки в том, что поле, которое вы хотите передать в квадратных скобках

не существует в текущем контексте

Когда вы пишите имя переменной, поля или свойства или чего угодно ещё, компилятор пытается это "что-то" найти в коде в определённых рамках. Когда вы пишите A, то (опустим многие вещи и другие случаи) компилятор смотрит: нет ли в текущем классе поля, свойства или переменной с именем A. Такого, как мы можем понять, нет, по-этому появляется ошибка.

Чтобы обратится к вашему статическому полю надо написать так:

Console.WriteLine(Program.Data[Program.A]);

Так компилятор поймёт, что вы имеете ввиду поле A класса Program.

В итоге рабочий код может выглядеть так:

using System.Collections.Generic;

class Program
{ 
    static readonly string A = "Key1";
    static readonly string B = "Key2";

    public static Dictionary<string, string> Data = new()
    {
        { A, "TestA" },
        { B, "TestB" }
    };
} 

class Print
{
    static void PrintConsole(string[] args) {
        Console.WriteLine(Program.Data[Program.A]);
    }
}

Или же можно вообще обойтись без этих полей:

using System.Collections.Generic;

class Program
{    
    public static Dictionary<string, string> Data = new()
    {
        { "Key1", "TestA" },
        { "Key2", "TestB" }
    };
} 

class Print
{
    static void PrintConsole(string[] args) {
        Console.WriteLine(Program.Data["Key1"]);
    }
}
→ Ссылка