Home > Software engineering >  C#: accessing Dictionary by using a partial class
C#: accessing Dictionary by using a partial class

Time:11-23

I'm trying to access a Dictionary in the following way, by using a partial class. The end purpose of this is to expose this dictionary and allow different methods to directly read/write from/to it.

FilenameABC.cs has this code, which seems to be OK for me so far:

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

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

FilenameDEF.cs has this code and this is where I'm having difficulties. I'm not sure why the .Add methods don't work. In the first one I'm trying to use it just after creating an instance of the ExampleDictionary class, which seems to be quite counter intuitive (given my current level of knowledge, of course). In the second one, I'm trying to add elements from inside a method, which is

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

Could anyone assist, please?

CodePudding user response:

The static method FunctionA cannot access instance members of ClassA.

Either change FunctionA to be non-static or make the dictionary field static.

CodePudding user response:

I still can't quite tell what you are trying to do. But I'll do my best to show you some stuff.

I'm taking this sentence you wrote: "The end purpose of this is to expose this dictionary and allow different methods to directly read/write from/to it." as my guide

Partial Class Issues

As I mentioned in the comments: there is no such thing as a Partial Class. The partial keyword simply indicates that a class may be defined in more than one file. The definition rules for the class remain the same, it's just that some of the class members may be defined in one file and other parts in other files.

The issues you are having here have nothing to do with the partial keyword.

Your Two // This does not work Notes

The first one looks like this:

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

The first line declares private member field of ClassA named instanceOfDict and initializes it. That's why it compiles.

The second line tries to put runnable code (a function call) directly in the top-level scope of a class. You can't do that. You can put a bunch of things at the top level scope of a class (e.g., fields, properties, methods, delegates, enums, inner classes), but you can't put code there.

Your second issue looks like this:

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

FunctionA is a static method. instanceOfDict is a private field of the class, not declared as static. You can't refer to instance to instance-level members (methods, properties, fields, ...) from a static method. Read up on the static keyword.

Creating a Class that Selectively Exposes a Dictionary

Since you want to do some dictionary work inside a class, but expose it to the outside, I went whole hog and made my class generic on <TKey, TValue> so that it works with Dictionaries of any type.

I also made it implement the Collection Initialization Pattern so that you can initialize instances of your class just like it was a dictionary.

To use the Collection Initialization Pattern, your class must do to things:

  1. Implement IEnumerable or IEnumerable<T> (T can be any type, not just the type you are collecting - you can even just throw a NotImplementedException if you don't care)

  2. Include a method that looks like public void Add (SomeType atLeastOneParameter). You can have more than one overload of Add if you want.

So, I start with this (Note that it implements 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();
    }
}

That's enough to make a class mostly look like a dictionary (your probably want to add some way to get the data, etc. But, that's up to you (you probably want to have an indexer (on TKey) and a TryGetValue.

But, let's add some more random functionality to the class (put this at the top level scope of the class):

    public int Count => _theDictionary.Count;

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

That will allow you to see how many things are in your dictionary and allow you to iterate over the items (the KeyValuePairs) that the Dictionary collections. Feel free to add more features.

Finally, to test this...

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

When I run this code, I get:

TestDict Count: 6
one
five
eight
ten
hundredFive
threeHundred

Splitting this using Partial

I don't know why you want to use partial class. Normally this is done to have two chunks of code that are edited/maintained by different personas (the typical reason is for Visual Studio's templating/wizarding mechanism to maintain one side of the partial class and the programmer the other.

The rules are pretty simple, you simply declare public partial class MyClass in two files. The two files must be in the same project (i.e., compiled into the same Assembly) and the classes must be in the same namespace. Once you do that, just split the (top-level scope) bits and pieces across the two partial class declarations.

In this cases I'd probably split it this way:

  • One one side, I'd put the two functions needed to implement the declared IEnumerator<TValue>:
    • public IEnumerator<TValue> GetEnumerator()
    • IEnumerator IEnumerable.GetEnumerator()
  • One the other side, I'd put everything else:
    • The dictionary declaration and intialization
    • The other enumerator: public IEnumerable<KeyValuePair<TKey, TValue>> GetKeyValuePairs()
    • public int Count => _theDictionary.Count;
    • public void Add(TKey key, TValue value)
  • Related