Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating an opaque pointer (reference) in C#

I have a class (basically a linked list, so let's call it List) that uses another class to store data (the nodes, so let's call the class Node). Node has methods that must be called from List, but calling them from elsewhere could be messy. I need other parts of my program to use references of Node, but to change them only through List.
In C++ I would create another class (let's call it Opaque) that has a private pointer to Node and expose some members of Node, and if this was passed to List, the pointer to the actual Node would be "unpacked" and used internally, but in C# I have not thought of a way to hide the reference to the Node from the rest of the program without also makking it inaccessible to List.
Is there any way to do it or some C#-specific idiom that has the same functionality?

CLARIFICATION: I would like to make it visible to the List class only. I already know about the internal keyword.

like image 850
Tomeamis Avatar asked Mar 18 '23 10:03

Tomeamis


2 Answers

What about

public interface INode
{
    string Name { get; }
}

public class List
{
    private class Node : INode
    {
        public string Name { get; set; }
        public Node Next { get; set; }
    }

    private List<Node> _items = new List<Node>();

    public INode GetItemAt(int index)
    {
        return _items[index];
    }

    public INode GetNextItem(INode item)
    {
        return (item is Node) ? ((Node)item).Next : null;
    }
}

Where only the INode would be publicly visible, implementation details hidden.

In case there would be lots of the internal code working with the Node then it is better to mark the class as internal as suggested by @eugene-podskal as then the Node class will be accessible to many "friends" living in the same original assembly (see MSDN: internal (C# reference) for more detailed description of this accessibility model)

There is nothing wrong per-se with the internal concept (as proposed and then disputed by @dasblinkenlight). It is also quite often used by the .NET framework, see http://referencesource.microsoft.com/#q=internal for examples or various .NET framework internal classes. An example of whole internal .NET framework namespaces can be seen using ILSpy e.g. at system.dll in namespace Microsoft.Win32.SafeHandles

like image 81
xmojmr Avatar answered Mar 25 '23 02:03

xmojmr


In C# has two levels of granularity for information hiding.

The most basic one is the class itself: this is the scope that you get when you declare a member private. This is not sufficient for your purposes, because the node and the list are different classes.

Next up is the level of the assembly, which is designated using the internal keyword. This is what you should be able to use for your purposes, assuming that the list class and the node class share the same assembly:

public class Node {
    internal void SpecialMethod() {
        ...
    }
}

The obvious downside is that the internal methods of the node class are visible to all classes inside your library, not only to the list. However, one could argue that internals of an opaque reference in C++ are visible to everyone who has access to the internal headers, so you get a closely matched functionality between the two languages.

like image 21
Sergey Kalinichenko Avatar answered Mar 25 '23 02:03

Sergey Kalinichenko