直接在C#中设置属性的属性

时间:2009-02-04 08:11:09

标签: c# .net properties

让我们考虑一下名为AvatarSize的公共属性,如下所示,

public class Foo
{
  ...

  public Size AvatarSize
  {
    get { return myAvatarSize; }
    set { myAvatarSize = value; }
  }

  ...
}

现在,如果目标类想要设置此属性,则需要按以下方式执行,

myFoo.AvatarSize = new Size(20, 20);  //this is one possible way

但如果我尝试这样设置,

myFoo.AvatarSize.Height = 20;  //.NET style
myFoo.AvatarSize.Width = 20;  //error

编译器给我一个错误,指出它无法修改返回值。我知道它为什么会发生,但我希望它也支持第二种方式。请帮我解决一下。

P.S。对不起,如果标题是荒谬的

7 个答案:

答案 0 :(得分:10)

Size是一个结构。作为ValueType,它是不可变的。如果你改变它的属性,它只会修改堆栈中的对象实例,而不是实际的字段。在您的情况下,AvatarSize属性只能使用结构构造函数设置:new Size(20, 20)

答案 1 :(得分:4)

你可以做你想做的唯一方法是定义

public class MutableSize{
  public int Height{get;set;}
  public int Width{get;set;}
}

然后让AvatarSize返回其中一个而不是Size。

答案 2 :(得分:4)

这实际上只是Petoj's answer的扩展。我不会选择一个可变的大小 - 在我看来,使事情变得更容易理解代码。

相反,引入两个新属性AvatarHeightAvatarWidth

public class Foo
{
  ...

  public Size AvatarSize
  {
    get { return myAvatarSize; }
    set { myAvatarSize = value; }
  }

  public int AvatarHeight
  {
    get { return AvatarSize.Height; }
    set { AvatarSize = new Size(AvatarWidth, value); }
  }

  public int AvatarWidth
  {
    get { return AvatarSize.Width; }
    set { AvatarSize = new Size(value, AvatarHeight); }
  }

  ...
}

您仍然无法撰写myFoo.AvatarSize.Width = 20,但可以撰写myFoo.AvatarWidth = 20。请注意,分别设置宽度和高度的效率低于一次设置它们的效率。

顺便说一句,这是Windows Forms采用的方法。

答案 3 :(得分:2)

您可以创建2个新属性myFoo.AvatarSizeWidth并使此属性更改宽度相同的高度..

答案 4 :(得分:2)

唯一的方法是将自己的Size类型作为类(引用)而不是struct(value)。

  public class Size
  {
    public Int32 Width;
    public Int32 Height;
  }

但这当然会使Size失去作为值类型的一些优点......

答案 5 :(得分:1)

这些Size对象是否具有Height和Width的写入属性?或者他们是只读的吗?

答案 6 :(得分:1)

如果要将结构视为类,则必须创建一个包含类,该类包含对结构类型的隐式转换。下面你可以看到包装类(名为Size,你可以根据需要命名它,没关系),Class1类有一个Size属性,然后是一个如何在Form1类中使用它的例子:

编辑:我使用逆转换(从System.Drawing.Size到此Size类)更新了Size类和一些注释。

public class Size
{
    public Size(){}

    public Size(int width, int height)
    {
        this.Width = width;
        this.Height = height;
    }

    public int Width { get; set; }

    public int Height { get; set; }

    static public implicit operator System.Drawing.Size(Size convertMe)
    {
       return new System.Drawing.Size(convertMe.Width, convertMe.Height);
    }

    static public implicit operator Size(System.Drawing.Size convertMe)
    {
       return new Size(convertMe.Width, convertMe.Height);
    }
}

class Class1
{
    public Class1()
    {
        this.TheSize = new Size();
    }

    public Size TheSize { get; set; }
}

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        /// Style 1.
        Class1 a = new Class1();

        a.TheSize = new Size(5, 10);

        /// Style 2.
        Class1 c = new Class1();

        c.TheSize.Width = 400;
        c.TheSize.Height = 800;

        /// The conversion from our Size to System.Drawing.Size
        this.Size = c.TheSize;

        Class1 b = new Class1();

        /// The opposite conversion
        b.TheSize = this.Size;

        Debug.Print("b Size: {0} x {1}", b.TheSize.Width, b.TheSize.Height);


    }
}