Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#参考文献;隐藏成员_C#_Oop_Friend_Double Pointer - Fatal编程技术网

C#参考文献;隐藏成员

C#参考文献;隐藏成员,c#,oop,friend,double-pointer,C#,Oop,Friend,Double Pointer,假设您有一个定义如下的类 public class SomeClass { public Manager m { get; protected set; } public SpecialData data { get; protected set; } //More methods and member code here... } 我需要我的manager类能够以某种方式更改SpecialData成员的集合引用。我可以用C++中的双指针或朋友类来实现这一点,但

假设您有一个定义如下的类

public class SomeClass
{
     public Manager m { get; protected set; }
     public SpecialData data { get; protected set; }

     //More methods and member code here...
}
我需要我的manager类能够以某种方式更改SpecialData成员的集合引用。我可以用C++中的双指针或朋友类来实现这一点,但在C语言中,这个选项是不可用的。如何保护SpecialData不受外部用户设置的影响,同时仍允许Manager类控制设置?我可以用internal关键字来做,但这看起来并不是非常安全或干净


非常感谢您的帮助。

如果manager类与
SomeClass
是同一程序集的一部分,使成员
内部
可以使同一程序集中的类访问setter:

public SpecialData data { get; protected internal set; }

类似于C++中使用<代码>朋友< /C> >,除了“友情”扩展到同一程序集的所有成员之外。


如果管理器是其他包的一部分,则可以在程序集上使用属性。但是,在这种情况下,您应该对扩展友谊的程序集进行签名,以避免试图从未经授权的代码访问setter。

创建一个继承
SomeClass
的类,该类的外观如下:

internal class SomeClassDecorator : SomeClass
{
    public void SetSpecialData(SpecialData value)
    {
        data = value;
    }
}

受保护意味着它可用于类的派生,并且由于
SomeClass
不是密封的,因此您可以简单地从它派生并执行任何需要的操作。然后可以使用此装饰器,而不是
SomeClass
本身。而且,您可以拥有所需的任意数量的装饰器,每个装饰器处理其特殊的
SpecialData

它可能并不完全是您想要的,但是所描述的
internal
关键字可以控制同一程序集中的访问;与C++中的<代码>朋友< /Cord>关键字类似。

可以使属性<代码>内部< /代码>。这将使属性仅在同一程序集中可见。或者,您可以使用
内部visibletoAttribute
来允许特定程序集访问该属性

另一种方法是使用
接口
隐藏该属性:

public interface ISomeClass
{
     Manager m { get; }
     SpecialData data { get; set; }
}

public class SomeClass : ISomeClass
{
     public Manager m { get; protected set; }
     SpecialData ISomeClass.data { get; set; }

     //More methods and member code here...
}
这样,
数据
只能从接口引用中看到

所以这不起作用:

SomeClass c = new SomeClass();
c.data;
但这确实:

ISomeClass c = new SomeClass();
c.data;

Manager
类上创建一个事件,类似于
RequestChangeSpecialData
事件,怎么样。
Manager
触发事件,
SomeClass
将更改
SpecialData
实例

public class SomeClass
{
     private  Manager _m;

     public Manager M 
     { 
        get { return _m} 
        set 
        {
            // register/unregister event on property assignment
            if(_m != null)
                _m.RequestChangeSpecialData -= RequestChangeSpecialData;

            _m = value;

            if(_m != null)
                _m.RequestChangeSpecialData += RequestChangeSpecialData;

        }
     }

     public SpecialData Data { get; private set; }

     private void RequestChangeSpecialData(object sender, ChangeSpecialDataEventArgs e)
     {
        // set the new reference
        Data = e.SpecialData;
     }

}

public class Manager
{
    public void DoSomething()
    {
        // the manager class wants to do something, and wants to change the SpecialData instance.., so it fires the event RequestChangeSpecialData


        SpecialData data = new SpecialData();

        // if the event is bound.
        if(RequestChangeSpecialData != null)
            RequestChangeSpecialData(this, new ChangeSpecialDataEventArgs(data));
    }

    public event EventHandler<ChangeSpecialDataEventArgs> RequestChangeSpecialData;
}

public class ChangeSpecialDataEventArgs : EventArgs
{
    public SpecialData Data {get; private set; }

    public ChangeSpecialDataEventArgs(SpecialData Data)
    {
        Data = data;
    }
}
公共类SomeClass
{
私人经理;;
公共经理
{ 
获取{return\m}
设置
{
//注册/取消注册财产转让事件
如果(_m!=null)
_m、 RequestChangeSpecialData-=RequestChangeSpecialData;
_m=值;
如果(_m!=null)
_m、 RequestChangeSpecialData+=RequestChangeSpecialData;
}
}
公共特殊数据数据{get;private set;}
私有无效请求ChangeSpecialData(对象发送方,ChangeSpecialDataEventArgs e)
{
//设置新的引用
数据=e.SpecialData;
}
}
公共班级经理
{
公共无效剂量测定法()
{
//manager类想要做一些事情,并且想要更改SpecialData实例..,因此它触发事件RequestChangeSpecialData
SpecialData=新的SpecialData();
//如果事件已绑定。
if(RequestChangeSpecialData!=null)
RequestChangeSpecialData(此,新的ChangeSpecialDataEventArgs(数据));
}
公共事件事件处理程序RequestChangeSpecialData;
}
公共类ChangeSpecialDataEventArgs:EventArgs
{
公共特殊数据数据{get;private set;}
公共更改SpecialData事件参数(SpecialData数据)
{
数据=数据;
}
}
未经测试(写在记事本中)


现在,
Manager
可以更改
SpecialData
属性。这样,管理器就不依赖于
SomeClass
/接口或程序集。

您能解释一下为什么认为
内部
不安全或不干净吗?你的意思是说它在一般情况下是这样的,还是说它不适合你的具体设计?我会说这是一个完美的解决方案,尽管说实话,我不知道你为什么要这么做。我确实提到了内部关键字。我知道这是一个选择,但这是一个好的选择吗?我担心有人认为这可能是一个设计缺陷。如果没有,这肯定会奏效。这是一个大项目,所以将它们结合在一起可能是一个大问题…@user3812869是的,
internal
是一个不错的选择。它是为这样的情况而设计的,当您设计一个共享内部表示知识的相关类包时。NET采取预防措施,不将这些知识泄露到您的库之外。想必,没有办法保护您的代码不受那些可以修改您的程序集的人的攻击。在这种情况下,我将尝试解决这些问题。我觉得这个设计有点奇怪。实际上,我有一个状态管理器和一个包含在游戏对象中的精灵。StateManager包含状态。这些状态需要编辑Sprite字段。@user3812869最后一位听起来确实有点奇怪,因为它听起来像
Sprite
是视觉表示的一部分,而其他一切都是模型的一部分。您最好更改排序的精灵标识符,并将它们“链接”到视图级别上的
sprite
对象。但这不会改变您在类中设置可访问性的方式,但是.was即将发布事件选项