-2

我有一堂课

public class Foo{
    public Foo{...}

    private void someFunction(){...}
    ...
    private Acessor{
        new Acessor
    }
}

具有一些私有功能(someFunction)。但是,有时,我想允许另一个类调用 Foo.SomeFunction,所以我有一个内部类访问 Foo 并传递:

public class Foo{
    public Foo{...}

    private void someFunction(){...}
    ...
    public Acessor{
        Foo _myFoo;
        new Acessor(Foo foo){_myFoo = foo;}
        public void someFunction(){
            _myFoo.someFunction();
        }
    }
}

使用这段代码,如果我想让 Foo 允许其他人调用 someFunction,Foo 可以传递一个新的 Foo.Accessor(this)。

不幸的是,这段代码允许任何人创建一个由 Foo 启动的 Foo.Accessor,并且他们可以访问 someFunction!我们不希望那样。但是,如果我们将 Foo.Accessor 设为私有,那么我们就不能将它从 Foo 中传递出去。

我现在的解决方案是让 Acessor 成为一个私有类,并让它实现一个公共接口 IFooAccessor;然后,我将 Foo.Accessor 作为 IFooAccessor 传递出去。这可行,但这意味着我必须声明 Foo.Accessor 在 IFooAccessor 中使用额外时间的每个方法。因此,如果我想重构这个方法的签名(例如,让 someFunction 带一个参数),我需要在三个地方引入更改。我不得不这样做好几次,它开始真正困扰我。有没有更好的办法?

4

3 回答 3

2

如果同一程序集中的类必须可以访问 someFunction,请使用 internal 而不是 private 修饰符。

http://msdn.microsoft.com/en-us/library/7c5ka91b(v=vs.71).aspx

如果它必须可供不在同一个汇编中的类访问,那么它应该是公共的。但是,如果它只被其他程序集中的几个类使用,您可能应该更好地考虑如何组织您的代码。

于 2012-12-09T19:03:35.350 回答
1

很难回答这个问题,因为不清楚(至少对我来说)你想要实现什么。(您在评论中写道make it difficult for someone to inadverdantly use this code)。

也许,如果该方法仅在特殊上下文中使用,那么显式实现接口可能是您想要的:

public interface ISomeContract {
    void someFunction();
}

public class Foo : ISomeContract {
    public Foo() {...}

    void ISomeContract.someFunction() {...}
}

这意味着,该类的客户必须将其转换ISomeContract为调用someFunction()

var foo = new Foo();
var x = foo as ISomeContract;
x.someFunction();
于 2012-12-09T19:30:34.570 回答
1

我有一个类似的问题。一个简单、优雅且易于理解的类,除了一个丑陋的方法必须在一层中调用,它不应该在食物链的更下游调用。尤其是不受这一类消费者的影响。

我最终做的是在我的类的普通调用者不会使用的单独命名空间中在我的基类上创建一个扩展。由于我的方法需要私有访问,这与 M4N 显示的显式接口实现相结合。

namespace MyProject.Whatever
{
    internal interface IHidden
    {
        void Manipulate();
    }

    internal class MyClass : IHidden
    {
        private string privateMember = "World!";

        public void SayHello()
        {
            Console.WriteLine("Hello " + privateMember);
        }

        void IHidden.Manipulate()
        {
            privateMember = "Universe!";
        }
    }
}

namespace MyProject.Whatever.Manipulatable
{
    static class MyClassExtension
    {
        public static void Manipulate(this MyClass instance)
        {
            ((IHidden)instance).Manipulate();
        }    
    }
}
于 2012-12-10T09:01:11.620 回答