วิธีที่ดีที่สุดในการทดสอบว่าประเภททั่วไปเป็นสตริงหรือไม่? (ค#)


95

ฉันมีคลาสทั่วไปที่ควรอนุญาตประเภทใดก็ได้ดั้งเดิมหรืออย่างอื่น default(T)ปัญหาเดียวกับนี้คือการใช้ เมื่อคุณเรียกค่าเริ่มต้นในประเภทค่าหรือสตริงค่าเริ่มต้นจะเริ่มต้นเป็นค่าที่เหมาะสม (เช่นสตริงว่าง) เมื่อคุณเรียกdefault(T)ใช้ออบเจ็กต์จะส่งกลับค่าว่าง ด้วยเหตุผลหลายประการเราจำเป็นต้องตรวจสอบให้แน่ใจว่าหากไม่ใช่ประเภทดั้งเดิมเราจะมีอินสแตนซ์เริ่มต้นของประเภทไม่ใช่ค่าว่าง นี่คือความพยายาม 1:

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

ปัญหา - สตริงไม่ใช่ประเภทค่า แต่ไม่มีตัวสร้างที่ไม่มีพารามิเตอร์ ดังนั้นวิธีแก้ปัญหาปัจจุบันคือ:

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

แต่นี่ให้ความรู้สึกเหมือนกากเดน มีวิธีที่ดีกว่าในการจัดการกับสายอักขระหรือไม่?

คำตอบ:


162

โปรดทราบว่าค่าเริ่มต้น (สตริง) เป็นโมฆะไม่ใช่สตริงว่างเปล่า คุณอาจต้องการกรณีพิเศษในรหัสของคุณ:

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

2
ฉันคิดว่าฉันลองวิธีแก้ปัญหาก่อนหน้านี้แล้วและมันไม่ได้ผล แต่ฉันต้องทำอะไรโง่ ๆ และขอขอบคุณที่ชี้ให้เห็นค่าเริ่มต้น (สตริง) ส่งคืนค่า null เรายังไม่พบข้อผิดพลาดเพราะมัน แต่นั่นเป็นเรื่องจริง
Rex M

1
@ Matt Hamilton: +1 แต่คุณควรอัปเดตคำตอบของคุณเพื่อส่งกลับ '(T) (object) String.Empty' ตามที่ CodeInChaos แนะนำเนื่องจากประเภทการส่งคืนวิธีเป็นแบบทั่วไปคุณไม่สามารถส่งคืนสตริงได้
VoodooChild

2
แล้วisคีย์เวิร์ดล่ะ? ที่นี่ไม่ใช้เหรอ?
Naveed Butt

ในขณะนี้เป็นไปไม่ได้ที่จะใช้โอเปอเรเตอร์ is กับชื่อสามัญและการมอบหมายงานหรืออินสแตนซ์โดยตรงใช่หรือไม่จะเป็นคุณสมบัติที่ยอดเยี่ยม
Juan Pablo Garcia Coello

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

ยังไม่ได้ทดสอบ แต่สิ่งแรกที่อยู่ในใจ


4

คุณสามารถใช้การแจงนับTypeCode เรียกใช้เมธอด GetTypeCode บนคลาสที่ใช้อินเทอร์เฟซ IConvertible เพื่อรับรหัสชนิดสำหรับอินสแตนซ์ของคลาสนั้น IConvertible ใช้งานได้โดย Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Char และ String ดังนั้นคุณสามารถตรวจสอบประเภทดั้งเดิมได้โดยใช้สิ่งนี้ ข้อมูลเพิ่มเติมเกี่ยวกับ "การตรวจสอบประเภททั่วไป "


2

โดยส่วนตัวแล้วฉันชอบวิธีการโอเวอร์โหลด:

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();
  }
}

0

ฉันรู้ว่าคำถามนี้เก่า แต่มีการอัปเดต

เนื่องจาก C # 7.0 คุณสามารถใช้ตัวisดำเนินการเพื่อเปรียบเทียบประเภทได้ คุณไม่จำเป็นต้องใช้typeofas ในคำตอบที่ยอมรับอีกต่อไป

        public bool IsObjectString(object obj)
        {
            return obj is string;
        }

https://docs.microsoft.com/en-US/dotnet/csharp/language-reference/keywords/is


-6

การสนทนาสำหรับ String ไม่ทำงานที่นี่

ฉันต้องมีรหัสต่อไปนี้สำหรับยาชื่อสามัญเพื่อให้มันใช้งานได้ -

   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
การทดสอบStringตามชื่อโดยเฉพาะอย่างยิ่งโดยไม่เกี่ยวข้องกับเนมสเปซนั้นไม่ดี และฉันไม่ชอบวิธีที่คุณแปลงด้วย
CodesInChaos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.