2

I want to be able to restrict usage of a instance variable to one method, and other usages should not be possible (compile error, or warning). For instance

public class Example
{
    public string Accessor()
    {
        if (SuperPrivate == null) // allowed
        {
            SuperPrivate = "test"; // allowed
        }

        return SuperPrivate; // allowed
    }

    private string SuperPrivate;

    public void NotAllowed()
    {
        var b = SuperPrivate.Length; // access not allowed
        SuperPrivate = "wrong"; // modification not allowed
    }

    public void Allowed()
    {
        var b = Accessor().Length; // allowed
        // no setter necessary in this usecase
    }
}

Usage of Lazy, automatic properties, or encapsulation in a separate object is not possible. I thought about extending ObsoleteAttribute, but it's sealed.

MrZarq
  • 258
  • 3
  • 12
  • 3
    You can't. I'd suggest you've probably modelled yourself into a corner if you think you need this - perhaps trying to enforce business rules via the C# type system rules? – Damien_The_Unbeliever Jan 28 '21 at 11:21
  • add a comment that says "write access is disallowed", and reprimand any developer not honoring this rule. – Franz Gleichmann Jan 28 '21 at 11:23
  • 1
    Why do you want to do this? – mjwills Jan 28 '21 at 11:24
  • It's not only write access that's disallowed, all access is only allowed through the Accessor method. – MrZarq Jan 28 '21 at 11:24
  • 1
    Can you explain to us _why_ you want to do this? Why do this rather than, say, split the class into two separate classes? – mjwills Jan 28 '21 at 11:30
  • I want to restrict access to the variable so it can't be accessed before it's initialized. Lazy or automatic properties don't work because it's async. And the team ruled against encapsulation in a separate class because it makes the code less readable and easy to navigate. – MrZarq Jan 28 '21 at 12:05
  • Even using reflexion in the get/set, and/or attributes as suggested by @MarcGravell, .NET and C# does not have such interesting behavior yet to allow the access of a data member or method to only specified or excluded methods. Thus you will only be able to control that at runtime, not at compile time, yet. I'm curious to know an answer with an implementation without having to code it since I don't have the time. Feel free to open a [feature request issue](https://devblogs.microsoft.com/visualstudio/introducing-suggest-a-feature-in-developer-community/) or to contact the .NET Dev Team please :) –  Jan 28 '21 at 12:46
  • Thus we should be able to create a special type to encapsulate this behavior where getter and setter will check some attributes to allow or disallow some methods to be called from : `AccessByMethodProtectedData` –  Jan 28 '21 at 12:49
  • @mjwills Annoyingly, in VB.Net you can have static locals (i.e. saved from function call to function call), but C# doesn't have them. really what we'd like is just to put braces around a function and a method and have the fields scoped only to that block. – Charlieface Jan 28 '21 at 13:25
  • @Charlieface Can you share an example? – mjwills Jan 28 '21 at 22:33
  • @mjwills See https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/modifiers/static What I would like is to write something like `{ private int _field; public void FuncUsingField() { ... } }` and have the `_field` not accesible even in the same class outside the block. It's useful for things like flags which need to be kept from run to run of a function – Charlieface Jan 29 '21 at 10:03

1 Answers1

4

That's not a thing that you can do out of the box. You could write a custom Roslyn analyzer that checks, for example, for an attribute of yours and adds a warning/error, but writing Roslyn analyzers is not trivial. It isn't entirely hard, either, note.

Consider:

// TODO: add an analyzer that checks for this attribute and applies the enforcement
[RestrictAccessTo(nameof(Accessor), nameof(Allowed))]
private string SuperPrivate;
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900