Reputation:
Lets consider that I have a public property called AvatarSize like the following,
public class Foo
{
...
public Size AvatarSize
{
get { return myAvatarSize; }
set { myAvatarSize = value; }
}
...
}
Now if a target class wants to set this property, then they need to do it the following way,
myFoo.AvatarSize = new Size(20, 20); //this is one possible way
But if I try to set it like this,
myFoo.AvatarSize.Height = 20; //.NET style
myFoo.AvatarSize.Width = 20; //error
the compiler get me an error stating that it cannot modify the return values. I know why it happens, but I would like it to support the second way also. Please help me with a solution.
P.S. Sorry if the title is absurd
Upvotes: 6
Views: 1046
Reputation: 1472
Size
is a structure. Being a ValueType it's immutable. If you change it's property like that, it will only modify an object instance in the stack, not the actual field. In your case AvatarSize
property can only be set using a struct constructor: new Size(20, 20)
.
Upvotes: 10
Reputation: 1500495
This is really just an expansion of Petoj's answer. I wouldn't go for a mutable size - making things mutable leads to harder to understand code in my view.
Instead, introduce two new properties, AvatarHeight
and AvatarWidth
:
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); }
}
...
}
You still can't write myFoo.AvatarSize.Width = 20
but you can write myFoo.AvatarWidth = 20
. Note that setting the width and height separately will be less efficient than setting them in one go.
This is the approach Windows Forms takes, by the way.
Upvotes: 4
Reputation: 5550
If you want to treat a struct like a class, you have to make a wrapper class that has an implicit conversion to the struct type. Below you can see the wrapper class (named Size, you can name it whatever you want, it doesn't matter), the Class1 class that has a Size property and then an example of how it's all used in the Form1 class:
EDIT: I updated the Size class with the inverse conversion (from System.Drawing.Size to this Size class) and some comments.
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);
}
}
Upvotes: 1
Reputation: 5221
The only way is to make your own Size type as a class (reference) instead of struct (value).
public class Size
{
public Int32 Width;
public Int32 Height;
}
But this will of course make the Size loose some of the advantages of being a value type...
Upvotes: 2
Reputation: 49629
The only way you can do what you want is by defining
public class MutableSize{
public int Height{get;set;}
public int Width{get;set;}
}
and then having AvatarSize return one of those instead of Size.
Upvotes: 4
Reputation: 12782
Does these Size object have write properties for Height and Width? Or are they readonly?
Upvotes: 1
Reputation: 38465
You could create 2 new properties myFoo.AvatarSizeWidth and make this property change the Width same goes for Height..
Upvotes: 2