2012-01-17 25 views
11

Nếu tôi đã tạo ra nhân viên đối tượng sau (giản thể) ...Đối tượng C# tùy chỉnh có chứa thuộc tính cùng loại với chính nó không?

public class Employee 
    { 
     public Employee() 
     {  
     } 

     public String StaffID { get; set; } 
     public String Forename { get; set; } 
     public String Surname { get; set; } 
    } 

... nó sẽ được chấp nhận để có một tài sản trong nhân viên đối tượng với một loại cũng là nhân viên để giữ chi tiết của Người quản lý (như được hiển thị bên dưới)?

public class Employee 
    { 
     public Employee() 
     {  
     } 

     public String StaffID { get; set; } 
     public String Forename { get; set; } 
     public String Surname { get; set; } 

     public Employee Manager { get; set; } 
    } 

Ngoài ra, cách tốt nhất để nhanh chóng nhân viên đối tượng cho quản lý bất động sản là gì? Rõ ràng bao gồm cả this.Manager = new Employee(); trong hàm tạo sẽ gây ra một vòng lặp vô hạn. Một lớp học Manager có thu nhập từ Nhân viên là cách tốt nhất (mặc dù tất cả các thuộc tính sẽ giống hệt nhau)?

+3

@FelixK. Thats một chút khắc nghiệt, một câu hỏi hay của nó và lấy một số quan tâm đọc này * .. trong constructor sẽ gây ra một vòng lặp vô hạn *. Hãy nhớ rằng tất cả không phải là chuyên gia – V4Vendetta

+0

@ V4Vendetta Đúng vậy, chúng tôi không phải là tất cả các chuyên gia. Nhưng khi tôi có một vấn đề hoặc câu hỏi tôi sẽ kiểm tra một số cách để giải quyết các nhiệm vụ gây ra vấn đề. –

+0

@FelixK. Có, tôi đã thử nó và nó biên soạn tốt - Đây là lý do tại sao câu hỏi của tôi là liệu nó có được chấp nhận hay không - nó có hoạt động không - tôi muốn kiểm tra xem đây có phải là thực hành tốt hay không nhiều hơn bất cứ điều gì. Khi nó xảy ra, các giải pháp dưới đây liên quan đến sự khởi tạo của đối tượng là khá nhiều những gì tôi đã kết luận quá nhưng một lần nữa, là tương đối thiếu kinh nghiệm, tôi muốn đảm bảo rằng tôi đã đi đúng hướng. – triplestones

Trả lời

17

Một đối tượng có thể thực sự có tham chiếu đến đối tượng thuộc loại riêng của nó.

Đây là cách thực hiện hầu hết các đối tượng loại Node.

Để khởi tạo - bạn có thể chuyển đối tượng Employee để sử dụng làm người quản lý (đi qua null không có người quản lý). Các nhà xây dựng có thể có nhiều tình trạng quá tải:

public Employee(Employee manager) 
{ 
    this.Manager = manager; 
} 
+1

+1, so sánh tốt với các loại 'Node'. – ken2k

+0

... nhưng rõ ràng bạn không nên vô điều kiện khởi tạo thuộc tính/trường trong hàm khởi tạo của bạn (vì điều đó sẽ gây ra 'StackOverflowException' hoặc' OutOfMemoryException', tùy thuộc vào kích thước của đối tượng, kích thước ngăn xếp được phân bổ và tổng thể của bạn bộ nhớ có sẵn). – Nuffin

+1

@Tobias Mã ở trên sẽ không gây ra bất kỳ ngoại lệ nào.Nó sẽ gây ra một nếu bạn khởi tạo nó với 'this.Manager = new Employee()'. –

7

Có, một đối tượng có thể chứa tham chiếu đến các đối tượng khác cùng một lớp.

Và thứ hai, tôi sẽ không tạo ra một nhân viên mới trong cunstructor nhưng tiêm nó như thế này:

public class Employee 
{ 
    public Employee(Employee manager) 
    { 
     this.Manager = manager; 
    } 

    public String StaffID { get; set; } 
    public String Forename { get; set; } 
    public String Surname { get; set; } 

    public Employee Manager { get; set; } 
} 
+0

+1 cho việc xây dựng tiêm! –

1

Nó hoạt động, bạn chỉ có thể cố gắng s.th. như:

public class A 
{ 
    public A test { get; set; } 
} 
2

Vâng, bạn có thể có Employee bên Employee và nó sẽ không gây ra vòng lặp vô hạn, theo mặc định Manager tài sản của đối tượng Employee sẽ null.

1

Cụ thể về vấn đề xây dựng (tôi đã +1 Odeds trả lời) - khi bạn nói xây dựng một thể hiện trong hàm tạo là một động thái xấu.

Nhưng sau đó hãy tự hỏi - tại sao bạn lại cần phải làm gì. Trong trường hợp Manager/Employee của bạn - bạn không thể luôn luôn chắc chắn rằng nhân viên luôn có người quản lý và nếu họ không làm như vậy, bạn không nên sử dụng phiên bản trống rỗng new để biểu thị điều đó, nhưng không có giá trị.

Khi loại của bạn sẽ có bộ nhận/đặt công khai trên thuộc tính, thường bạn có khả năng tải các cây đối tượng này từ một số nguồn bên ngoài, trong trường hợp đó bạn không có gì phải lo lắng. Tương tự, bạn có thể có một hàm tạo chấp nhận các trường hợp Employee khác cho các mối quan hệ Người quản lý/Nhân viên, v.v.

Bạn cũng nên kiểm tra các mối quan hệ vòng tròn trong hàm tạo đó - tức làmột nhân viên không thể là người quản lý của một người nào đó và nhân viên của họ - hãy thử đi theo đứa trẻ-> mối quan hệ cha mẹ cho điều đó và xem liệu nó có bao giờ kết thúc không!

0

Đầu tiên, câu trả lời là một đối tượng có thể có trường chứa bản sao của chính nó. Nó thậm chí có thể có phương pháp mà chấp nhận hoặc trả lại trường hợp của cùng lớp, và nó thậm chí có thể phụ thuộc vào bản thân trong định nghĩa của lớp, ví dụ:

public class Person : IComparable<Person> //legal, recursive definition 
{ 
    //fields (or properties) that are of type Person 
    public Person Father; 
    public Person Mother; 
    public List<Person> Children; 

    // method that takes a Person as a parameter 
    public bool IsParent(Person potentialParent) 
    { 
     .... 
    } 

    //method that returs a Person 
    public Person Clone() 
    { 
     //TODO: real implementation coming soon 
    } 

    public Person(){} 

    //constructor that takes persons as arguments 
    public Person(Person father, Person Mother) 
    { 
     Father = father; 
     Mother = mother; 
    } 
} 

Theo mặc định tất cả các giá trị tham chiếu là null 'd vì vậy bạn sẽ không có vấn đề về nhà xây dựng trừ khi bạn tự tạo một vấn đề. Vì vậy, , có thể có một số vấn đề với tham chiếu vòng tròn và vòng lặp vô tận (mỗi phụ huynh có con có con có bố mẹ vv ..) nhưng thường chúng có thể được phát hiện và tránh trivially.

Lần duy nhất tôi gặp phải các loại sự cố này là khi tôi sử dụng chuỗi tuần tự hóa XML (hoặc dựa trên văn bản khác) trên các đối tượng được tham chiếu vòng tròn.

3

Kịch bản duy nhất tại đây không phải là có thể là với struct; a struct được chứa trực tiếp (thay vì tham chiếu kích thước cố định cho dữ liệu), do đó, kích thước của cấu trúc Employee sẽ phải là "kích thước của các trường khác cộng với kích thước của nhân viên". .

Đặc biệt bạn không thể có:

struct Foo { 
    Foo foo; 
} 

(hoặc bất cứ điều gì khác mà có thể dẫn đến một kích thước hình tròn) - trình biên dịch phản ứng với:

viên

Struct 'Foo.foo' thuộc loại 'Foo' gây ra một chu kỳ trong bố cục struct

Tuy nhiên, trong mọi trường hợp khác thì tốt; với vấn đề initialisation, tôi muốn nói: chỉ cần để nó unassigned ban đầu, và để cho người gọi chỉ định một giá trị thông qua tài sản.

0

tôi đã cố gắng theo cách này và nó làm việc cho tôi:

class Program 
{ 
    static void Main(string[] args) 
    { 
     A a = new A(new A()); 
    } 
} 

public class A 
{ 
    public string Name { get; set; } 
    public A a; 

    public A() { } 
    public A(A _a) 
    { 
     a = _a; 
    } 
} 

Bây giờ bạn có thể sử dụng nó trong Main() chức năng như:

class Program 
{ 
    static void Main(string[] args) 
    { 
     A a = new A(new A()); 
     a.Name = "Roger"; 
     a.a.Name = "John"; 
     Console.WriteLine("{0}, {1}", a.Name, a.a.Name); 
    } 
} 
Các vấn đề liên quan