2011-01-26 24 views
28

tôi thường kiểm tra đối số nhà xây dựng cho các giá trị null trong các cách sau đây:Kiểm tra tham số constructor for null trước khi gọi cơ sở

public class SomeClass(SomeArgument someArgument) 
{ 
    if(someArgument == null) throw new ArgumentNullException("someArgument"); 
} 

Nhưng nói rằng tôi có một lớp kế thừa từ một lớp khác:

public abstract class TheBase 
{ 
    public TheBase(int id) 
    { 

    } 
} 

public class TheArgument 
{ 
    public int TheId { get; set; } 
} 

public class TheInheritor : TheBase 
{ 
    public TheInheritor(TheArgument theArgument) : base(theArgument.TheId) 
    { 

    } 
} 

Và ai đó hiện đang tạo một phiên bản của TheInheritor như sau:

var theVar = new TheInheritor(null); 

Tôi không thể mực của một cách để kiểm tra null trước khi base đang được gọi (và ném một NullReferenceException). Ngắn cho phép một nhà xây dựng của TheBase chấp nhận một thể hiện của TheArgument Tôi không thể thấy làm thế nào tôi có thể kiểm tra sự lành mạnh này. Nhưng điều gì sẽ xảy ra nếu TheArgument chỉ liên quan đến TheInheritor và có rất nhiều lớp khác được kế thừa từ TheBase?

Bất kỳ đề xuất nào về cách giải quyết vấn đề này?

Trả lời

40

Bạn có thể làm điều đó với một cái gì đó như thế này:

public TheInheritor(TheArgument theArgument) 
    : base(ConvertToId(theArgument)) 
{ 
} 

private static int ConvertToId(TheArgument theArgument) 
{ 
    if (theArgument == null) 
    { 
     throw new ArgumentNullException("theArgument"); 
    } 
    return theArgument.Id; 
} 

Hoặc tổng quát hơn, một cái gì đó như thế này:

public TheInheritor(TheArgument theArgument) 
    : base(Preconditions.CheckNotNull(theArgument).Id) 
{ 
} 

nơi Preconditions là một lớp tiện ích khác, như thế này:

public static class Preconditions 
{ 
    public static T CheckNotNull<T>(T value) where T : class 
    { 
     if (value == null) 
     { 
      throw new ArgumentNullException(); 
     } 
     return value; 
    } 
} 

(Điều này mất tên đối số, tất nhiên, nhưng bạn cũng có thể vượt qua điều đó nếu nec essary.)

+0

thực hiện một chức năng trên một tham số? Đó có phải là luôn luôn trong C#? Chưa bao giờ thấy điều đó trước đây. Nhưng có vẻ đẹp;) (hoặc là nó?) –

+0

Công cụ tuyệt vời. Tự hỏi tại sao tôi không nghĩ về điều đó. Học mỗi ngày :-) +1 –

+0

Tôi nghĩ tôi thích cách tiếp cận chung hơn nữa. Cảm ơn Jon. –

0

Theo nguyên tắc chung, tôi sẽ chỉ lo lắng về các thông số tôi đang sử dụng trong lớp học của mình. Các tham số chỉ được sử dụng bởi lớp cơ sở, tôi sẽ chuyển thẳng qua và để cho lớp đó lo lắng về nó.

0

Bạn có thể gọi các nhà xây dựng cơ sở như thế này (vì lợi ích của các đối số giả định -1 chỉ ra một giá trị không hợp lệ):

public class TheInheritor : TheBase 
    { 
     public TheInheritor(TheArgument theArgument) : base(theArgument == null ? -1 : theArgument.TheId) 
     { 
       if (theArgument == null) 
       { 
        throw new ArgumentNullException("theArgument"); 
       } 

     } 
    } 
+0

Điều này sẽ cho phép cá thể được tạo thành những gì có thể được giả định là một trạng thái không hợp lệ. –

+0

@Fredrik: Đúng, thay đổi việc triển khai một chút. Nhưng dù sao thì tôi cũng thích Jon hơn nữa. –

1

Là một thay thế, bạn có thể sử dụng một Func <> để lựa chọn id:

public class TheInheritor : TheBase 
{ 
    public TheInheritor(TheArgument theArgument, Func<TheArgument, int> idSelector) 
     : base(idSelector(theArgument)) 
    { 
     ... 
    } 
} 

hoặc thậm chí

public class TheInheritor<T> : TheBase where T : TheArgument 
{ 
    public TheInheritor(T theArgument, Func<T, int> idSelector) 
     : base(idSelector(theArgument)) 
    { 
     ... 
    } 
} 

Các trường hợp ngoại lệ sẽ rơi vào họ của riêng bạn, cũng như bạn sẽ buộc các callee để quyết định làm thế nào để xác định các đối tượng của Id.

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