0

我有一个有 6 个属性的类,它们基本上是 3 对属性,每对包含关于一件事的数据。所有这些属性都是公开的,但设置它们是受保护的。它显示在下面的代码中:

public class MyClass
{
    public Data1Type Item1Data1 { get; protected set; }
    public Data2Type Item1Data2 { get; protected set; }
    public Data1Type Item2Data1 { get; protected set; }
    public Data2Type Item2Data2 { get; protected set; }
    public Data1Type Item3Data1 { get; protected set; }
    public Data2Type Item3Data2 { get; protected set; }
}

因为每一对属性基本上都被视为一个项目,所以我决定制作一个如下所示的结构:

struct Item
{
    Data1Type Data1;
    Data2Type Data2;
}

Item所以我用一个结构替换了每一对属性。

我现在面临的问题是,我无法找到一种方法来获得与以前相同的保护级别,并具有 3 对属性。我希望外部MyClass的所有内容都能够获取Item结构内部的属性,但只有MyClass从它派生的类才能更改Item结构内部的属性。

我怎么能做这样的事情?甚至可能吗?

4

4 回答 4

3

您可以将结构设为只读以保留对值的控制。这是 .NET 中使用的一种模式:

struct MyStruct
{
    public readonly int Field1;
    public readonly int Field2;

    public MyStruct(int i, int j)
    {
        Field1 = i;
        Field2 = j;
    }
}

然后,您可以像以前一样创建属性,知道结构内的值将保持不变,除非您通过属性设置器。

于 2013-02-01T15:55:02.530 回答
2

只需使用受保护的 setter 创建结构类型的属性:

public class MyClass
{
    public Item Item1 { get; protected set; }
    public Item Item2 { get; protected set; }
    public Item Item3 { get; protected set; }
}

Struct 是一种值类型,因此客户端无法从 MyClass 更改项目Data1Data2属性(客户端将拥有项目的副本)。使用受保护的 setter,只有 MyClass 及其继承者可以为 item 设置新值。如果您希望为某个项目更新项目的数据,请使用class而不是struct.

于 2013-02-01T15:51:21.247 回答
0

您可能应该阅读更多关于struct- 它意味着是immutable,这意味着您不应该能够更改 anItem的属性,无论是MyClass从其他任何地方还是从其他任何地方。

如果您查看Stan Petrovs 的答案,您可以了解应该如何制作结构。

然后你MyClass应该有类似的东西:

protected void SetItem1Data1(DataType1 newValue) 
{
    this.Item1 = new Item(newValue, this.Item1.Data2);
}
于 2013-02-01T15:59:02.800 回答
0

只有两种方式可以使用以下构造:

someThing.someMember.nestedMember = someValue;

可以是合法的:要么someMember返回对类实例的引用,在这种情况下someThing,一旦引用返回, 的参与就会停止,或者someThing.someMember必须是 class 的字段someThing。即使someMember返回一个结构,它在 C# 中也是合法的,以允许someMember可能执行以下操作:

public class Thing { ...
    private nestedType member_nestedMember;
    public struct MemberProxy {
        Thing _owner;
        internal MemberProxy(Thing owner) {_owner = owner;}
        nestedType nestedMember {
            get {return _owner.member_nestedMember;}
            set {_owner.member_nestedMember = value; }
        }
    }
    public MemberProxy someMember {get {return new MemberProxy(this);} }
}

在这种情况下,MemberProxy实际上并不保存 的数据nestedMember,而是保存对它所包含的实际位置的引用。因此,即使 的实例MemberProxy不可写,尝试设置其nestedMember属性也是可行的。不幸的是,即使在某些情况下,在只读结构值上调用属性设置器会有所帮助(ArraySegment将提供另一个这样的示例),但目前还没有定义属性来告诉编译器何时应该或应该这样做不被允许。

回到您目前的情况,我建议如果您的类型或派生类型可能希望更改项目的一部分而不更改两者,那么您最好的选择可能是声明您的复合材料的开放字段结构-项目类型并包含在protected该类型的类字段中,以及返回它们的公共属性。这样做可以让你的派生类说:

item1.Data1 = whatever;

虽然外部代码必须使用该Item1属性,即使Data1是一个暴露的可写类型字段Item,尝试说:

item1.Data1 = whatever;

不会编译[请注意,如果Data1是读/写属性,即使是旧的编译器也会接受这样的声明,理论上它可能有用,当它Data1是一个字段时会正确地拒绝它]。如果您决定不公开公共可变结构,您可以随时执行以下操作:

public struct Item
{
   privateItem Value;
   public Type1 Data1 {get {return Value.Data1; }}
   public Type1 Data2 {get {return Value.Data2; }}
   Item(privateItem src)
   {
     Value = src;
   }
 }

我个人认为添加额外的包装层没有任何价值,但它可能有助于安抚“公共可变结构是邪恶的”人群。

于 2013-02-02T17:29:51.390 回答