我有一个C#类,其中一个字段需要从类外部可见,但应该只在类中更改。但是,问题是该字段是通过公共mutator方法更新的,而不是直接(或由属性)更新:
public class FirstClass
{
public SecondClass TheField {get; private set;}
public FirstClass()
{
TheField = new SecondClass();
}
public void SomeMethod()
{
// ...
TheField.Update(/*parameters*/);
// ...
}
}
public class SecondClass
{
// some fields
public SecondClass() { }
public void Update(/*parameters*/)
{
// do something
}
}
换句话说,我希望方法Update()只能从FirstClass中访问。
几种可能的解决方案以及我对它们不满意的原因:
有办法做到这一点吗?
答案 0 :(得分:4)
@ aquaraga答案的基本实现,但改为使用接口:
public interface ISecond
{
// some properties
}
public class FirstClass
{
private readonly SecondClass _TheField;
public ISecond TheField { get { return _TheField; } }
public FirstClass()
{
_TheField = new SecondClass();
}
public void SomeMethod()
{
// ...
_TheField.Update(/*parameters*/);
// ...
}
private class SecondClass : ISecond
{
// some properties
public void Update(/*parameters*/)
{
// do something
}
}
}
基本上,公开一个包含所有可访问成员但没有Update
方法的公共接口。使用一个私有嵌套类,它具有Update
方法,但在调用代码时无法访问,并将其作为接口公开,而不是作为类。
一些示例用法:
FirstClass myFirst = ...
myFirst.SomeMethod(); //updates ok!
Console.WriteLine(myFirst.TheField.PropertyA); //can access properties of ISecond
myFirst.TheField.Update(); //compiler error!
有一点是你提到使用“某些领域”;作为一个接口,你将无法拥有字段而是属性。我不确定这对你来说是否是违规行为。
编辑:您提到了重用SecondClass
并尽量减少代码重复的意图。一个快速解决方法可能是声明一些abstract
类,protected Update
方法,使用internal
构造函数(因此其他程序集不能从中继承),然后公开{{1}用最小的实现调用:
Update
然后在你的public abstract class SecondClassBase : ISecond
{
// some properties
internal SecondClassBase()
{
}
protected void Update(/*parameters*/)
{
// do something
}
}
中,除嵌套类外没有任何变化:
FirstClass
仍有一些代码重复,但您现在需要做的就是复制/粘贴代码;无需为public class FirstClass
{
private readonly SecondClass _TheField;
public ISecond TheField { get { return _TheField; } }
public FirstClass()
{
_TheField = new SecondClass();
}
public void SomeMethod()
{
// ...
_TheField.Update(/*parameters*/);
// ...
}
private class SecondClass : SecondClassBase
{
public new void Update(/*parameters*/)
{
base.Update(/*parameters*/);
}
}
}
的每个实现重新声明属性或Update
逻辑。您还可以将FirstClass
方法重命名为其他方法以避免方法隐藏,但我想我会保留您之前使用的相同调用签名。
答案 1 :(得分:1)
一种方法是将一个名为UpdateableSecondClass
的子类作为FirstClass的内部类。
它将继承自SecondClass
,并且只有一个方法:Update()
您的SecondClass
根本不应该使用Update()
方法。你可以继续将它暴露给世界其他地方:
public SecondClass TheField {get; private set;}
答案 2 :(得分:1)
我认为你可以使用这种模式:
public partial class FirstClass {
partial class ThirdClass: SecondClass {
public void PerformUpdate(/* parameters */) {
base.Update(/* parameters */);
}
}
public void SomeMethod() {
}
public FirstClass() {
}
public SecondClass TheProperty {
get {
return m_TheField;
}
}
ThirdClass m_TheField=new ThirdClass();
}
public partial class SecondClass {
protected void Update(/* parameters */) {
}
public SecondClass() {
}
}
ThirdClass
继承自SecondClass
,但未公开。该属性作为SecondClass
类型的实例公开,但实际上是ThirdClass
类型的字段。
方法SecondClass.Update
仅暴露给派生类。您可以声明SecondClass
公开,而不是嵌套,但保持对私有的更新。
答案 3 :(得分:0)
public class FirstClass
{
private SecondClass TheField { get; set; }
public void SomeMethod()
{
TheField.Update( /*parameters*/);
}
private class SecondClass
{
public void Update( /*parameters*/)
{
// do something
}
}
}
答案 4 :(得分:0)
Chris Sinclair回答很棒,这只是另一种选择
public sealed class FirstClass : SecondClass
{
public FirstClass()
{
}
public void SomeMethod(int j)
{
base.Update(j);
}
}
public abstract class SecondClass
{
public SecondClass() { }
protected void Update(int i)
{
Console.WriteLine(i.ToString());
}
}
这只是通过FirstClass
访问方法的部分