2009-02-04 32 views
6

Cho phép xem xét rằng tôi có một tài sản công cộng gọi AvatarSize như sau,Thiết sở hữu tài sản của trực tiếp trong C#

public class Foo 
{ 
    ... 

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

    ... 
} 

Bây giờ nếu một lớp đối tượng muốn đặt khách sạn này, sau đó họ cần phải làm điều đó theo cách sau ,

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

Nhưng nếu tôi cố gắng thiết lập nó như thế này,

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

trình biên dịch làm cho tôi một lỗi nói rằng nó không thể sửa đổi các giá trị trả lại. Tôi biết tại sao nó xảy ra, nhưng tôi cũng muốn nó hỗ trợ cách thứ hai. Xin hãy giúp tôi với một giải pháp.

P.S. Xin lỗi nếu tiêu đề là ngớ ngẩn

+0

Bạn có thể vui lòng nêu rõ lý do bạn muốn nó hoạt động theo cách này không? Tôi sợ không có nhiều lựa chọn, ngoài những gì Petoj nói. –

+0

Vui lòng cho biết cách "Kích thước" trông như thế nào. –

+0

Kích thước là loại giá trị .Net chuẩn trong không gian tên System.Drawing. – bang

Trả lời

10

Size là cấu trúc. Là một ValueType nó không thay đổi. Nếu bạn thay đổi thuộc tính của nó như thế, nó sẽ chỉ sửa đổi một cá thể đối tượng trong ngăn xếp, chứ không phải trường thực tế. Trong trường hợp của bạn, bạn chỉ có thể đặt thuộc tính AvatarSize bằng cách sử dụng hàm tạo cấu trúc: new Size(20, 20).

+0

Nó không thực sự là bất biến mà làm cho một vấn đề - ngay cả khi đây là một cấu trúc có thể thay đổi, bạn vẫn có cùng một vấn đề vì giá trị trả về từ thuộc tính sẽ bị hủy liên kết khỏi biến đó. –

+0

Thực ra, OP nói rằng anh ta biết tại sao vấn đề xảy ra. Tôi cho rằng anh ta chỉ đang tìm cách đánh máy ít hơn khi anh ấy chỉ phải thiết lập một trong những đặc tính ... Vì vậy, câu trả lời của tôi là bọc nó trong một lớp học. Tôi không thực sự nghĩ đó là ý tưởng tốt nhất để thực sự làm, nhưng nếu bạn thực sự muốn, nó có thể được thực hiện. –

2

Bạn có thể tạo ra 2 thuộc tính mới myFoo.AvatarSizeWidth và thực hiện thay đổi thuộc tính này cùng Width đi cho Chiều cao ..

+0

Tôi không muốn theo cách đó. Nó sẽ không giải quyết, myFoo.AvatarSize.Height = 20; //.NET style myFoo.AvatarSize.Width = 20; // error vấn đề này –

+0

@Sudarsan: Bạn đã hiểu lầm câu trả lời. Nó gợi ý bạn sẽ viết myFoo.AvatarSizeHeight = 20. –

1

Liệu những Kích đối tượng có quyền ghi thuộc tính cho Height và Width? Hay là họ chỉ đọc?

+0

Chúng có tính chất ghi –

+0

No. Kích thước là imutable. Bạn không thể thay đổi bất kỳ giá trị nào của nó. Đó là lý do tại sao trình biên dịch rên rỉ. –

4

Cách duy nhất bạn có thể làm những gì bạn muốn là bằng cách định nghĩa

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

và sau đó có AvatarSize trở lại một trong những người thay vì Kích.

2

Cách duy nhất là tạo loại Kích thước của riêng bạn thành lớp (tham chiếu) thay vì cấu trúc (giá trị).

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

Nhưng điều này sẽ đương nhiên làm cho Kích mất một số lợi thế trở thành một kiểu giá trị ...

1

Nếu bạn muốn đối xử với một cấu trúc giống như một lớp, bạn phải thực hiện một lớp wrapper có một chuyển đổi ẩn đối với kiểu cấu trúc. Dưới đây bạn có thể thấy lớp wrapper (có tên là Size, bạn có thể đặt tên nó là gì, không quan trọng), class Class1 có thuộc tính Size và sau đó là ví dụ về cách nó được sử dụng trong lớp Form1:

EDIT: Tôi đã cập nhật lớp Kích thước với chuyển đổi nghịch đảo (từ System.Drawing.Size thành lớp Kích thước này) và một số nhận xét.

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); 


    } 
} 
+0

Nếu đây là casse, sau đó làm thế nào để xử lý Add() cho một tài sản thuộc loại IList ?? tức là, làm cách nào để tôi cho phép sử dụng myFoo.AvatarList = new IList () cũng myFoo.AvatarList.Add ("foo"); Nếu tôi phải làm theo cách của bạn, sau đó nó trở nên tẻ nhạt phải không ?? –

+0

Tôi xin lỗi vì tôi không thấy cách liên quan đến câu hỏi gốc. Câu hỏi của bạn là về tài sản AvatarSize, không có gì về một danh sách. –

+0

Xem lớp Form1 trong mã của tôi, nó làm mọi thứ bạn yêu cầu. –

4

Đây thực sự chỉ là bản mở rộng Petoj's answer. Tôi sẽ không đi cho một kích thước có thể thay đổi - làm cho mọi thứ có thể biến đổi dẫn đến khó hiểu mã trong quan điểm của tôi.

Thay vào đó, giới thiệu hai thuộc tính mới, 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); } 
    } 

    ... 
} 

Bạn vẫn không thể viết myFoo.AvatarSize.Width = 20 nhưng bạn thể viết myFoo.AvatarWidth = 20. Lưu ý rằng việc thiết lập chiều rộng và chiều cao một cách riêng biệt sẽ kém hiệu quả hơn là đặt chúng trong một lần.

Đây là cách tiếp cận mà Windows Forms thực hiện.

Các vấn đề liên quan