c#公共字段,只能从类内部更新
本文关键字:内部 更新 字段 | 更新日期: 2023-09-27 18:17:19
我有一个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内部访问。
几个可能的解决方案和我不满意的原因:
- 将SecondClass更改为setter而不是method。-不会工作,因为我需要有参数和很多东西要做。
- 将Update()设为内部而不是公共。-仍然可以从组装中访问,不够好。
- 从FirstClass修改SecondClass,即将方法Update()移动到FirstClass,使其为私有,并从SecondClass公开所有需要的字段。-感觉不是很面向对象。
- 从SecondClass构造函数调用Update(),并在每次需要更新时创建一个新的SecondClass实例。性能会受到影响,因为在SecondClass中有一些东西永远不会改变,我希望每次调用Update()时都处理它。
有办法做到这一点吗?
@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!
有一点是你提到使用"some fields";作为一个接口,你不能有字段,只能有属性。我不确定这对你来说是否是个坏消息。
编辑:您提到您打算重用SecondClass
并尽量减少代码重复。一个快速修复可能是声明一些abstract
类,protected Update
方法,使用internal
构造函数(因此其他程序集不能从它继承),然后用最小实现公开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*/);
}
}
}
仍然有一些代码重复,但你现在需要做的就是复制/粘贴代码;不需要为FirstClass
的每个实现重新声明属性或Update
逻辑。您还可以将new Update
方法重命名为其他内容以避免方法隐藏,但我认为我会保留您之前使用的相同调用签名。
一种方法是创建一个名为UpdateableSecondClass
的子类作为FirstClass的内部类。它将继承SecondClass
,并有一个方法:Update()
你的SecondClass
不应该有Update()
方法。你可以继续向世界其他地方展示它:
public SecondClass TheField {get; private set;}
我认为你可以使用这个模式:
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
声明为公共的,而不是嵌套的,但是保持对文件的更新为私有的。
如何使用嵌套类型
public class FirstClass
{
private SecondClass TheField { get; set; }
public void SomeMethod()
{
TheField.Update( /*parameters*/);
}
private class SecondClass
{
public void Update( /*parameters*/)
{
// do something
}
}
}
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