【问题标题】:How to define a struct whose members can be accessed by any internal classes but can only be set by a particular (internal) class?如何定义一个结构,其成员可以被任何内部类访问,但只能由特定(内部)类设置?
【发布时间】:2010-07-22 08:04:50
【问题描述】:

如何定义一个结构,其成员可以被任何内部类通过属性访问,但只能由特定的内部类设置? (如果可能的话。)

如果不可能,是否有办法实现类似的要求?

编辑1:下面

原因:

我有一个有两个成员 _x 和 _arrB 的 A 类。 _x 可以被内部类(A 类除外)通过 x 读取但不能修改。

我还希望允许内部类读取 _arrB 中的 structB 元素并读取这些 structB 的成员。但我只希望 A 类能够修改 _arrB 中的 structB 元素或那些 structB 的成员。因此,我认为我需要一个可以指定哪些内部类可以修改其成员的结构。[1]

class A 
{
    private int _x;
    internal int x
    {
        private set
        {
            _x = value / 2;
        }
        internal get
        {
            return _x * 2;
        }
    }

    private B[] _arrB;
    internal B[] arrB
    { 
        private set
        {
            _arrB = value;
        }
        internal get
        {
            return _arrB;
        }
    }

    public A() 
    {
        _x = //value read from somewhere;            

        //do something to determine size
        _arrB = new B[size];
        //populate _arrB
        ...
    }


}

注意:内部类是指同一程序集中的类,而不是嵌套类。

[1] 但是,_arrB 是一个数组,它是一个对象,它是一个引用类型。当内部类获得 _arrB 的引用时,structB 的元素可能会在不受控制的情况下被修改。我意识到我不希望内部类将 _arr[0] 设置为空。所以任何解决方案都必须考虑到这一点。

我会在剩下的时间里考虑它,并在我想到一个解决方案时发布一个解决方案。

【问题讨论】:

  • 对我来说听起来像是一股巨大的代码味道。
  • 我已经用更多信息更新了我的问题。事实上,我也能闻到代码的味道。我想我还有很多东西要学,编程还有很长的路要走。 :)
  • 如果不关心集合中的对象成员是否被修改,只想禁止集合修改。使用ReadOnlyCollection<T>。

标签: c# class properties struct internal


【解决方案1】:

我想知道你为什么要这样做。只有丑陋的黑客是可能的AFAIK。

开始警告:如果您不喜欢丑陋的代码,请不要阅读!!!

大卫·尼尔说了什么。

您可以将它们放在单独的程序集中并将它们设置为友好:

[assembly:InternalsVisibleToAttribute("assembly name", "key")]

你可以这样设计这个类:

internal struct ModifiedStruct
{
    public int Value {get; private set; }

    internal class ModifyingClass
    {
        public void ModifyValue()
        {
            ModifiedStruct s = new ModifiedStruct();
            s.Value = 456;
        }
    }

}

结束警告

编辑(问题已更改) 要禁止修改集合,请使用ReadOnlyCollection Class。

internal ReadOnlyCollection<B> BCollection
{
    get
    {
        return new ReadOnlyCollection<B>(_arrB);
    }
}

【讨论】:

  • 感谢您对使用 ReadOnlyCollection 的建议。有了它,我可以实现更优雅、更易读的解决方案。
  • typo: 应该是 ReadOnlyCollection,但我知道你的意思。
【解决方案2】:

我唯一能想到的就是使用堆栈跟踪来获取调用帧,然后是调用方法,然后是该方法的反射类型。然后,您可以检查该类型是否符合您的预期。

编辑、警告、错误代码:

StackTrace oStack = new StackTrace(true);

string callingType = oStack.GetFrame(1).GetMethod().ReflectedType.FullName;

if(callingType != "MyAcceptableClass")
    throw new MethodAccessException(
          callingType + " is not allowed to call this method");

我个人会重新考虑您的设计,也许这些类不应该在同一个程序集中?然后,您可以使两个程序集成为朋友程序集,以便它们可以访问彼此的内部成员。

【讨论】:

  • 是的,我正在重新考虑设计。鉴于我目前的知识,我不太了解您的解决方案。不过还是谢谢。
  • 以上是我的想法,但我不建议使用它。
【解决方案3】:

如果可以在其字段中创建具有特定值的结构,则该结构类型的任何可变存储位置都可以通过创建具有这些值的实例然后将该实例复制到存储位置来改变以保存这些值有问题。说struct1=struct2 相当于说struct1.field1 = struct2.field1; struct1.field2 = struct2.field2; 等对结构类型的所有公共和私有字段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 2019-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多