2013-07-24 81 views
6

Xét đoạn mã sau:Sử dụng loại động thay vì tài sản chung không-thể

public dynamic DataGrid { get; private set; } 
    public DataGridForm<TData, TGrid> GridConfig<TData, TGrid>() where TData : class 
    { 
     return DataGrid = new DataGridForm<TData, TGrid>(); 
    } 

Tôi đang cố gắng để giữ một thể hiện của một lớp học chung trong một property để sử dụng sau, nhưng như bạn biết:

Thuộc tính, sự kiện, nhà thầu vv không thể là chung chung - chỉ có các phương pháp và các loại có thể là chung chung. Phần lớn thời gian đó không phải là một vấn đề, nhưng tôi đồng ý rằng đôi khi nó là một nỗi đau (Jon Skeet)

Tôi muốn biết đây là một cách tốt để làm tròn tình huống này?

+0

Bạn không thể đặt chức năng chung trong Giao diện 'IDataGridForm' và sau đó có thuộc tính thuộc loại đó? – Corak

+0

Tôi không thể giúp bạn, bạn có thể giải thích chi tiết hơn không? – saber

+2

Vâng, bạn muốn * sử dụng * 'DataGridForm' như thế nào? Ví dụ, tôi tưởng tượng bạn muốn 'hiển thị' một biểu mẫu. Vì vậy, hãy tạo một giao diện 'IDataGridForm' với phương thức' Display() '. Bây giờ hãy để lớp của bạn 'DataGridForm ' thực hiện giao diện đó. Nó cần phải có phương thức 'Display()' để làm điều đó. Bây giờ có một thuộc tính 'public IDataGridForm DataGrid {get; bộ tư nhân; } '. Thuộc tính này bây giờ có thể chứa một 'DataGridForm ' và bạn có thể 'Hiển thị()' nó bất cứ nơi nào bạn muốn. – Corak

Trả lời

1

Như câu trả lời trong các bình luận chỉ ra, bạn có thể làm điều này với một lớp cơ sở hoặc một giao diện:

class DataGridForm {} 
class DataGridForm<TData, TGrid> : DataGridForm {} 

class GridConfigurator 
{ 
    public DataGridForm DataGrid { get; private set; } 
    public DataGridForm<TData, TGrid> GridConfig<TData, TGrid>() where TData : class 
    { 
     return DataGrid = new DataGridForm<TData, TGrid>(); 
    } 
} 

Một tấn các loại và các giao diện trong C# đã được mở rộng theo cách này khi Generics được thêm vào. Tuy nhiên, tôi có lẽ sẽ đánh giá lại thiết kế của bạn để có lẽ bất cứ điều gì gọi là GridConfig() đã được bộ nhớ đệm DataGridForm vì nó biết các loại. Ví dụ: tôi thực hiện một điều rất giống với mã của mình:

class Vector<T> { ... } 
static class Vector 
{ 
    public static Vector<T> Create<T>(T value) 
    { 
     return new Vector<T>(value); 
    } 
} 

class OtherClass 
{ 
    public static Vector<int> MyVector = Vector.Create(1); 
} 

Trường hợp sử dụng cụ thể của bạn có thể không hỗ trợ kiểu này.

+0

Tôi nhận ra những gì bạn giải thích không phù hợp với yêu cầu của tôi, nếu tôi có để có một phương thức trong 'DataGridForm' trả về' DataGridForm '. Trong tình huống này tôi đã làm cho các loại cơ sở một loại chung quá. Tôi có đúng không? – saber

+0

Không phải nếu nó là một phương pháp, nhưng có nếu nó là một tài sản. Trong ví dụ thứ 2 của tôi, Vector có thể kế thừa từ Vector mà không gặp vấn đề gì. – lukegravitt

+0

Không phải loại trả lại của Vector.Create là Vector ? – marcob

0

Trong trường hợp này, chính loại của bạn phải là loại chung.

class GridConfigurator<TData, TGrid> 
     where TData : class 
    { 
     public DataGridForm<TData, TGrid> DataGrid { get; private set; } 
     public DataGridForm<TData, TGrid> GridConfig<TData, TGrid>() 
     { 
      return DataGrid = new DataGridForm<TData, TGrid>(); 
     } 
    } 

Nhưng tôi không hiểu mục đích của lớp học này. Phương thức GridConfig có một tác dụng phụ không rõ ràng của việc thiết lập thuộc tính DataGrid (có một setter riêng). Nếu tôi đang sử dụng lớp này, tôi sẽ không bao giờ đoán rằng giá trị GridConfig() trả về cho tôi cũng được đặt làm thuộc tính DataGrid. Nói cách khác:

var configurator = new GridConfigurator(); 
var firstGrid = configurator.GridConfig(); 
var firstReference = configurator.DataGrid; 
var secondGrid = configurator.GridConfig(); 
var secondReference = configurator.DataGrid; 

tôi sẽ giả định sau đây sẽ trả về false:

object.ReferenceEquals(firstGrid, secondGrid); 

Nhưng tôi sẽ giả định này sẽ quay trở lại đúng:

object.ReferenceEquals(firstReference, secondReference); 

Bởi vì tại không có điểm trong mã trên tôi đã bao giờ gán thuộc tính DataGrid. Nó không phải là rõ ràng rằng một phương pháp gọi là GridConfig() sẽ có hiệu lực đó.

Tạo kiểu kèm theo (GridConfigurator) cũng có vẻ chung chung để đánh bại mục đích của những gì bạn đang cố gắng. Tại sao bất cứ ai sử dụng loại này khi họ chỉ có thể sử dụng một tham chiếu trực tiếp đến DataGridForm thay thế?

Nếu phương pháp GridConfig là phải làm một cái gì đó nhiều hơn chỉ là gán một trường hợp mặc định mới của DataGridForm, sau đó làm cho nó một lớp nhà máy tĩnh như thế này:

static class GridConfigurator 
{ 
    public static DataGridForm<TData,TGrid> GridConfig<TData, TGrid>(...) where TData: class 
    { 
    var grid = new DataGridForm<TData,TGrid>(); 
    // do something with the parameters to this method to initialize the instance. 
    return grid; 
    } 
} 

Tôi cũng sẽ đặt tên cho phương pháp một cái gì đó khác hơn GridConfig. Giống như Configure() hoặc Create().