Cách tốt nhất để kiểm tra xem loại chung có phải là một chuỗi không? (C #)


93

Tôi có một lớp chung sẽ cho phép bất kỳ kiểu nào, nguyên thủy hoặc cách khác. Vấn đề duy nhất với điều này là sử dụng default(T). Khi bạn gọi mặc định trên một kiểu giá trị hoặc một chuỗi, nó sẽ khởi tạo nó thành một giá trị hợp lý (chẳng hạn như chuỗi trống). Khi bạn gọi default(T)một đối tượng, nó sẽ trả về null. Vì nhiều lý do khác nhau, chúng ta cần đảm bảo rằng nếu nó không phải là một kiểu nguyên thủy, thì chúng ta sẽ có một thể hiện mặc định của kiểu, không phải null. Đây là nỗ lực 1:

T createDefault()
{
    if(typeof(T).IsValueType)
    {
        return default(T);
    }
    else
    {
        return Activator.CreateInstance<T>();
    }
}

Vấn đề - chuỗi không phải là một kiểu giá trị, nhưng nó không có hàm tạo không tham số. Vì vậy, giải pháp hiện tại là:

T createDefault()
{
    if(typeof(T).IsValueType || typeof(T).FullName == "System.String")
    {
        return default(T);
    }
    else
    {
        return Activator.CreateInstance<T>();
    }
}

Nhưng điều này cảm thấy giống như một bùn. Có cách nào tốt hơn để xử lý trường hợp chuỗi không?

Câu trả lời:


161

Hãy nhớ rằng mặc định (string) là null, không phải string.Empty. Bạn có thể muốn một trường hợp đặc biệt trong mã của mình:

if (typeof(T) == typeof(String)) return (T)(object)String.Empty;

2
Tôi nghĩ rằng tôi đã thử giải pháp đó sớm hơn và nó không hiệu quả, nhưng tôi chắc chắn đã làm điều gì đó ngu ngốc. Và cảm ơn bạn đã chỉ ra default (string) trả về null, chúng tôi chưa gặp lỗi vì nó, nhưng đó là sự thật.
Rex M

1
@Matt Hamilton: +1, nhưng bạn nên cập nhật câu trả lời của mình để trả về '(T) (đối tượng) String.Empty' như CodeInChaos đề xuất vì kiểu trả về của phương thức là chung chung, bạn không thể chỉ trả về chuỗi.
VoodooChild

2
Còn istừ khóa thì sao? Đó không phải là sử dụng ở đây?
Naveed Butt,

Tại thời điểm này là không thể áp dụng các nhà điều hành với Generics và chuyển nhượng hoặc instancing trực tiếp, không phải là nó ?, sẽ là một tính năng thú vị
Juan Pablo Garcia Coello

14
if (typeof(T).IsValueType || typeof(T) == typeof(String))
{
     return default(T);
}
else
{
     return Activator.CreateInstance<T>();
}

Chưa được thử nghiệm, nhưng điều đầu tiên xuất hiện trong tâm trí.


4

Bạn có thể sử dụng kiểu liệt kê Mã loại. Gọi phương thức GetTypeCode trên các lớp triển khai giao diện IConvertible để lấy mã loại cho một phiên bản của lớp đó. IConvertible được thực hiện bởi Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Char và String, vì vậy bạn có thể kiểm tra các kiểu nguyên thủy bằng cách sử dụng điều này. Thông tin thêm về " Kiểm tra Loại Chung ".


2

Cá nhân tôi thích nạp chồng phương thức:

public static class Extensions { 
  public static String Blank(this String me) {      
    return String.Empty;
  }
  public static T Blank<T>(this T me) {      
    var tot = typeof(T);
    return tot.IsValueType
      ? default(T)
      : (T)Activator.CreateInstance(tot)
      ;
  }
}
class Program {
  static void Main(string[] args) {
    Object o = null;
    String s = null;
    int i = 6;
    Console.WriteLine(o.Blank()); //"System.Object"
    Console.WriteLine(s.Blank()); //""
    Console.WriteLine(i.Blank()); //"0"
    Console.ReadKey();
  }
}


-6

Cuộc thảo luận cho Chuỗi không hoạt động ở đây.

Tôi phải có mã sau cho generic để làm cho nó hoạt động -

   private T createDefault()
    { 

        {     
            if(typeof(T).IsValueType)     
            {         
                return default(T);     
            }
            else if (typeof(T).Name == "String")
            {
                return (T)Convert.ChangeType(String.Empty,typeof(T));
            }
            else
            {
                return Activator.CreateInstance<T>();
            } 
        } 

    }

3
Kiểm tra Stringtheo tên, đặc biệt là không liên quan đến không gian tên là không tốt. Và tôi cũng không thích cách bạn chuyển đổi.
CodesInChaos
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.