2013-06-13 12 views
51

Tôi có phương pháp chung chung sau đây, nhưng VS cho tôi một lỗi biên dịch trên đó. (Toán tử '??' không thể áp dụng cho các toán hạng kiểu 'T' và 'T')Toán tử '??' không thể áp dụng cho các toán hạng kiểu 'T' và 'T'

public static T Method<T>(T model) where T : new() 
{ 
    var m = model ?? new T(); 
} 

Có ai biết tại sao không?

Chỉnh sửa: Có thể lý do là T có thể là cấu trúc trong trường hợp của tôi không và cấu trúc có phải là một loại không có giá trị không?

Trả lời

53

Bạn nên thêm class chế:

public static T Method<T>(T model) where T : class, new() 
{ 
    var m = model ?? new T(); 

    return m; 
} 

Và bạn nên trở m quá!

Lưu ý: Như @KristofDegrave nêu trong bình luận của ông, lý do mà chúng ta phải thêm class hạn chế là vì T có thể là một kiểu giá trị, như int và kể từ ?? điều hành (null-coalescing) kiểm tra trên các loại có thể được null , vì vậy, chúng tôi phải thêm ràng buộc class để loại trừ các loại giá trị.

Chỉnh sửa: Câu trả lời của Alvin Wong cũng đề cập đến trường hợp cho các loại có thể vô hiệu; đó là cấu trúc thực sự, nhưng có thể là toán hạng của ?? nhà điều hành. Chỉ cần lưu ý rằng Method sẽ trả về null mà không có phiên bản quá tải của Alvin, đối với các loại có thể vô hiệu hóa.

+0

tại sao ông nên 'trở lại m' thay vì' trở lại mô hình ?? new T(); 'tôi nghĩ kết quả sẽ giống nhau? – WiiMaxx

+2

Tất nhiên chúng giống nhau! Nhưng trong câu hỏi số 1 được sử dụng. Nó chỉ là tôi đã đề cập. –

+3

Có thể lý do là T có thể là một cấu trúc trong trường hợp của tôi không, và cấu trúc là một kiểu không nullable? –

8

Bạn cần phải xác định rằng loại T của bạn là một lớp học với một hạn chế vào loại chung:

public static T Method<T>(T model) where T : class, new() 
{ 
    return model ?? new T(); 
} 
4

Kể từ khi T có thể là bất kỳ kiểu, không có gì bảo đảm rằng T sẽ có một tĩnh ?? toán tử hoặc kiểu T là nullable.

?? Operator (C# Reference)

Các ?? toán tử được gọi là toán tử kết hợp null và được sử dụng để xác định giá trị mặc định cho các loại giá trị có thể vô hiệu hoặc tham chiếu các loại.

83

?? là toán tử kết hợp rỗng. Nó không thể được áp dụng cho các loại không nullable. Vì T có thể là bất kỳ thứ gì, nó có thể là một loại int hoặc loại nguyên thủy, không có giá trị khác.

Nếu bạn thêm điều kiện where T : class (phải được chỉ định trước new()), nó buộc T làm phiên bản lớp, không có giá trị.

+0

Không mới() lực lượng điều kiện T là một loại nullable? –

+3

@KristofDegrave no new() chỉ có nghĩa là sẽ có một construtor rỗng – WiiMaxx

+0

Có thể lý do là T có thể là một struct trong trường hợp của tôi, và struct là một kiểu không nullable? –

0

model ?? new T() có nghĩa là model == null ? new T() : model. Nó không được đảm bảo rằng mô hình là không nullable và == không thể được áp dụng cho null và một đối tượng không nullable. Việc thay đổi ràng buộc thành where T : class, new() sẽ hoạt động.

0

Đánh dấu T là "lớp" và bạn tốt.

4

Đối với một số lý do các nhà điều hành ?? không thể được sử dụng trên các loại nullable, mặc dù nó được coi là tương đương với model == null ? new T() : model, và bạn phép so sánh null với một loại nullable.

Bạn có thể có được chính xác những gì bạn đang tìm kiếm không có bất kỳ hạn chế bổ sung bằng cách sử dụng toán tử ternary thay vào đó, hoặc một câu lệnh if:

public static T Method<T>(T model) where T : new() 
{ 
    var m = model == null ? new T() : model; 
} 
+0

Điều này không thể xử lý các loại 'Nullable <>'. Nó trả về 'null' khi' mô hình' là 'null'. –

+1

@AlvinWong Vâng, 'var m = new int?()' Được cho là 'null'. Đối với các kiểu giá trị, 'new T()' tương tự (nếu không chính xác giống như) 'default (T)'. Nếu bạn muốn khởi tạo các kiểu nullable thành một cái gì đó khác với kết quả của hàm tạo mặc định, thì mã này là không đầy đủ, nhưng đó không phải là câu hỏi của OP. –

31

Nhiều người đã chỉ ra rằng đã thêm class hạn chế cho generic sẽ giải quyết vấn đề.

Nếu bạn muốn phương pháp của bạn sẽ được áp dụng đối với Nullable<T> quá, bạn có thể thêm một tình trạng quá tải cho nó:

// For reference types 
public static T Method<T>(T model) where T : class, new() 
{ 
    return model ?? new T(); 
} 

// For Nullable<T> 
public static T Method<T>(T? model) where T : struct 
{ 
    return model ?? new T(); // OR 
    return model ?? default(T); 
} 
+0

Tnx để chỉ ra rằng, nhưng tôi không cần phải hỗ trợ nó cho các giá trị struct :) –

+10

@KristofDegrave Chỉ cần chỉ ra cho đầy đủ. Người khác có thể cần nó! :) –