开发者

Restricting scope of a class member beyond private

I was wondering if there was a way to scope acc开发者_开发知识库ess of a class member specifically to get/set implementations in c# to reduce the chance of me accidentally accessing them directly. Something like private but only allows get/set to access it, I was thinking that I could wrap each variable in their own class but that seems overkill for the restriction I'm looking for. Thanks


You can add [Obsolete("Use the property")] to the field and suppress the warning in the property by writing #pragma warning disable 618.


No, unfortunately not. I assume you'd be after something like this:

// Not actually valid C#!
public string Name
{
    // Only accessible within the property
    string name;

    get { return name; }
    set
    {
        if (value == null)
        {
            throw new ArgumentNullException();
        }
        name = value;
    }
}

I've wanted something like this before, too. Unfortunately it's not possible :(


This is not possible. The only access modifiers are private, internal, protected, protected internal and public and none fit the bill.

If you use an auto-property, however, then of course you can only access it by get and set.


If you don't need to do any operations in the accessors, use a auto-implemented property.

I'm guessing most likely you DO want to do operations and that's why you want to make sure you use the property instead of the backing field.

In that case consider the following:

  • Use a naming convention like "_instanceName" to indicate a private member field. (You should be doing this anyhow ...)
  • When you feel the operations inside your accessors are common, and reuseable, encapsulate it in a class. Don't worry about overkill until you run into performance issues.

I believe I might have found a possible workaround, and it is surprisingly small. This 'solution' might be a bit too clever however. Perhaps I'll do some benchmarking tests tomorrow. Problem is at the moment it is also scoped over every place it is used, perhaps by using generics this can be limited.

It makes use of the fact that lambdas always have the same backing method. By passing a lambda to a static constructor, a static object can keep track of this unique 'scope' and link variables to it. More details about this implementation can be found here.

Usage:

class LocalTestClass
{
    public int StaticTest( int setValue )
    {
        Local<int> test = Local<int>.Static( () => { } );
        int before = test.Value;
        test.Value = setValue;
        return before;
    }

    public int InstanceTest( int setValue )
    {
        Local<int> test = Local<int>.Instance( () => this );
        int before = test.Value;
        test.Value = setValue;
        return before;
    }
}

[TestMethod]
public void LocalStaticTest()
{
    LocalTestClass instance1 = new LocalTestClass();
    LocalTestClass instance2 = new LocalTestClass();

    instance1.StaticTest( 10 );
    Assert.AreEqual( 10, instance2.StaticTest( 20 ) );
    Assert.AreEqual( 20, instance1.StaticTest( 30 ) );
}

[TestMethod]
public void LocalInstanceTest()
{
    LocalTestClass instance1 = new LocalTestClass();
    LocalTestClass instance2 = new LocalTestClass();

    instance1.InstanceTest( 10 );
    Assert.AreEqual( 10, instance1.InstanceTest( 20 ) );
    instance2.InstanceTest( 50 );
    Assert.AreEqual( 20, instance1.InstanceTest( 30 ) );
}

The class:

public class Local<TValue>
{
    static readonly Dictionary<object, object> StaticScope
        = new Dictionary<object, object>();
    static readonly Dictionary<object, Dictionary<object, object>> InstanceScope
        = new Dictionary<object, Dictionary<object, object>>();


    public TValue Value { get; set; }


    private Local() { }


    public static Local<TValue> Static( Action scope )
    {
        if ( !StaticScope.ContainsKey( scope ) )
        {
            Local<TValue> newInstance = new Local<TValue>();
            StaticScope.Add( scope, newInstance );                
        }

        return StaticScope[ scope ] as Local<TValue>;
    }

    public static Local<TValue> Instance<TScope>( Func<TScope> scope )
    {
        object instance = scope();
        if ( !InstanceScope.ContainsKey( instance ) )
        {                
            InstanceScope.Add( instance, new Dictionary<object, object>() );

            if ( !InstanceScope[ instance ].ContainsKey( scope ) )
            {
                Local<TValue> newInstance = new Local<TValue>();
                InstanceScope[ instance ].Add( scope, newInstance );
            }
        }

        return InstanceScope[ instance ][ scope ] as Local<TValue>;
    }
}

A more general discussion about this topic can be found on Programmers.SE.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜