C#: доступ к словарю с помощью частичного класса

0

Вопрос

Я пытаюсь получить доступ к Словарю следующим образом, используя частичный класс. Конечная цель этого состоит в том, чтобы предоставить доступ к этому словарю и разрешить различным методам прямое чтение/запись из/в него.

В файле FilenameABC.cs есть этот код, который пока кажется мне приемлемым:

namespace Namespace1
{
    partial class ClassA
    {
        public class ExampleDictionary
        {
            private Dictionary<int, string> _dict;

            public ExampleDictionary()
            {
                _dict = new Dictionary<int, string>();
            }
        }
    }
}

В файле FilenameDEF.cs есть этот код, и именно здесь у меня возникают трудности. Я не уверен, почему методы .Add не работают. В первом я пытаюсь использовать его сразу после создания экземпляра класса ExampleDictionary, что кажется довольно противоречивым (учитывая мой текущий уровень знаний, конечно). Во втором я пытаюсь добавить элементы из метода, который является

namespace Namespace1
{
    partial class ClassA
    {
        ExampleDictionary instanceOfDict = new ExampleDictionary();
        instanceOfDict.Add(1, "Test1"); // This does not work

        public static void FunctionA()
        {            
            for (int i = 0; i < 10; i++)
            {
            string text = $"Test{i}";
            instanceOfDict.Add(i, text); // This does not work as well              
            }          
        }
    }
}

Кто-нибудь может помочь, пожалуйста?

2
1

Статический метод FunctionA не удается получить доступ к членам экземпляра ClassA.

Либо изменить FunctionA быть нестатичным или сделать поле словаря статичным.

2021-11-22 16:28:57
1

Я все еще не могу до конца понять, что вы пытаетесь сделать. Но я сделаю все возможное, чтобы показать тебе кое-что.

Я беру это предложение, которое вы написали: "Конечная цель этого-раскрыть этот словарь и разрешить различным методам напрямую читать/записывать из/в него". В качестве моего руководства.

Неполные Проблемы с Классами

Как я уже упоминал в комментариях: не существует такого понятия, как Частичный класс. Ключевое слово partial просто указывает, что класс может быть определен более чем в одном файле. Правила определения класса остаются прежними, просто некоторые члены класса могут быть определены в одном файле, а другие части-в других файлах.

Проблемы, с которыми вы здесь сталкиваетесь, не имеют ничего общего с partial ключевое слово.

Ваши двое // Это не работает Примечания

Первый выглядит так:

partial class ClassA
{
    ExampleDictionary instanceOfDict = new ExampleDictionary();
    instanceOfDict.Add(1, "Test1"); // This does not work
    //other code
}

В первой строке объявляется поле закрытого участника ClassA названный instanceOfDict и инициализирует его. Вот почему он компилируется.

Вторая строка пытается поместить выполняемый код (вызов функции) непосредственно в область верхнего уровня класса. Ты не можешь этого сделать. Вы можете поместить кучу вещей в область верхнего уровня класса (например, поля, свойства, методы, делегаты, перечисления, внутренние классы), но вы не можете поместить туда код.

Ваша вторая проблема выглядит так:

public static void FunctionA()
{            
    for (int i = 0; i < 10; i++)
    {
        string text = $"Test{i}";
        instanceOfDict.Add(i, text); // This does not work as well              
    }          
}

Функция-это static метод. instanceOfDict является закрытым полем класса, не объявленным как статическое. Вы не можете ссылаться на экземпляр на элементы уровня экземпляра (методы, свойства, поля,...) из статического метода. Прочитайте о static ключевое слово.

Создание класса, который выборочно предоставляет словарь

Поскольку вы хотите выполнить некоторую работу со словарем внутри класса, но выставить его снаружи, я пошел на все и сделал свой класс универсальным на <TKey, TValue> так что он работает со словарями любого типа.

Я также заставил его реализовать шаблон инициализации коллекции, чтобы вы могли инициализировать экземпляры своего класса так же, как это был словарь.

Чтобы использовать шаблон инициализации коллекции, ваш класс должен выполнять определенные действия:

  1. Осуществлять IEnumerable или IEnumerable<T> (T может быть любого типа, а не только того, который вы собираете - вы даже можете просто бросить NotImplementedException если тебе все равно)

  2. Включите метод, который выглядит следующим образом public void Add (SomeType atLeastOneParameter). У вас может быть более одной перегрузки Add если ты хочешь.

Итак, я начинаю с этого (обратите внимание, что он реализует IEnumerable<T>:

public partial class TestExposedDictionary<TKey, TValue> : IEnumerable<TValue>
{
    private readonly Dictionary<TKey, TValue> _theDictionary = new Dictionary<TKey, TValue>();

    public void Add(TKey key, TValue value)
    {
        _theDictionary.Add(key, value);
    }

    public IEnumerator<TValue> GetEnumerator()
    {
        foreach (var kvp in _theDictionary)
        {
            yield return kvp.Value;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

Этого достаточно, чтобы класс в основном выглядел как словарь (вы, вероятно, хотите добавить какой-то способ получения данных и т. Д. Но это зависит от вас (вы, вероятно, хотите иметь индексатор (на TKey) и а TryGetValue.

Но давайте добавим в класс еще несколько случайных функций (поместите это в область верхнего уровня класса).:

    public int Count => _theDictionary.Count;

    public IEnumerable<KeyValuePair<TKey, TValue>> GetKeyValuePairs()
    {
        foreach (var kvp in _theDictionary)
        {
            yield return kvp;
        }
    }

Это позволит вам увидеть, сколько вещей есть в вашем словаре, и позволит вам перебирать элементы (в KeyValuePairs) что Словарные коллекции. Не стесняйтесь добавлять дополнительные функции.

Наконец, чтобы проверить это...

public static void Test()
{
    var testDict = new TestExposedDictionary<int, string> {
        {1, "one" },
        {5, "five" },
        {8, "eight" },
        {10, "ten" },
        {105, "hundredFive" },
    };

    // I can call Add in the normal way as well:
    testDict.Add(300, "threeHundred");

    Console.WriteLine($"TestDict Count: {testDict.Count}");
    foreach (string s in testDict)
    {
        Console.WriteLine(s);
    }
}

Когда я запускаю этот код, я получаю:

TestDict Count: 6
one
five
eight
ten
hundredFive
threeHundred

Разделение этого с помощью частичного

Я не знаю, почему вы хотите использовать partial class. Обычно это делается для того, чтобы иметь два фрагмента кода, которые редактируются/поддерживаются разными персонажами (типичная причина заключается в том, что механизм шаблонов/волшебства Visual Studio поддерживает одну сторону partial class а программист другой.

Правила довольно просты, вы просто заявляете public partial class MyClass в двух файлах. Два файла должны находиться в одном проекте (т. Е. скомпилированы в одну сборку), а классы должны находиться в одном пространстве имен. Как только вы это сделаете, просто разделите (область верхнего уровня) по частям на два partial class заявления.

В этом случае я бы, вероятно, разделил его таким образом:

  • С одной стороны, я бы поставил две функции, необходимые для реализации объявленного IEnumerator<TValue>:
    • public IEnumerator<TValue> GetEnumerator()
    • IEnumerator IEnumerable.GetEnumerator()
  • С другой стороны, я бы поставил все остальное:
    • Объявление и инициализация словаря
    • Другой перечислитель: public IEnumerable<KeyValuePair<TKey, TValue>> GetKeyValuePairs()
    • public int Count => _theDictionary.Count;
    • public void Add(TKey key, TValue value)
2021-11-23 01:45:02

Я не могу выразить, как я благодарен за это. Это также помогло мне избавиться от нескольких заблуждений, которые у меня были. Иногда изучение программирования вызывает разочарование, но, к счастью, есть такие удивительные люди, как вы, которые посвящают часть своего дня помощи другим. Еще раз спасибо!
roccaforte

Да, я знаю. К счастью, я только что получил этот значок, который позволяет мне, как новичку, начать торговать такой валютой. :-)
roccaforte

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................