বস্তু সি # তে জেনেরিক ধরণের হয় কিনা তা পরীক্ষা করা হচ্ছে


134

যদি কোনও বস্তু জেনেরিক ধরণের হয় তবে আমি একটি পরীক্ষা করতে চাই। আমি সাফল্য ছাড়াই নিম্নলিখিত চেষ্টা করেছি:

public bool Test()
{
    List<int> list = new List<int>();
    return list.GetType() == typeof(List<>);
}

আমি কী ভুল করছি এবং আমি এই পরীক্ষাটি কীভাবে করব?

উত্তর:


201

যদি আপনি এটি জেনেরিক ধরণের উদাহরণ হিসাবে পরীক্ষা করতে চান:

return list.GetType().IsGenericType;

আপনি যদি এটি জেনেরিক কিনা তা পরীক্ষা করতে চান List<T>:

return list.GetType().GetGenericTypeDefinition() == typeof(List<>);

জন যেমন উল্লেখ করেছেন, এটি সঠিক ধরণের সমতুল্যতা পরীক্ষা করে। প্রত্যাবর্তনের falseঅর্থ অগত্যা অর্থ list is List<T>ফেরৎ হয় না false(যেমন বস্তুটি কোনও List<T>ভেরিয়েবলের জন্য বরাদ্দ করা যায় না )।


9
এটি যদিও সাব টাইপগুলি সনাক্ত করে না। আমার উত্তর দেখুন। এটি ইন্টারফেসের জন্যও অনেক কঠিন :(
জন স্কিটি

1
জেনেরিক টাইপডিফাইনিশনে কলটি জেনেরিক ধরণের না হলে নিক্ষেপ করবে। নিশ্চিত হয়ে নিন যে আপনি প্রথমে এটি পরীক্ষা করেছেন।
কিলহোফার

85

আমি ধরে নিলাম যে আপনি টাইপটি জেনেরিক কিনা তা কেবল জানতে চান না, তবে কোনও বিষয় যদি কোনও নির্দিষ্ট জেনেরিক ধরণের উদাহরণ, প্রকারের আর্গুমেন্টগুলি না জেনে।

দুর্ভাগ্যক্রমে, এটি মারাত্মক সহজ নয়। জেনেরিক টাইপটি যদি একটি শ্রেণি হয় তবে এটি খুব খারাপ নয় (যেমনটি এটি ক্ষেত্রে রয়েছে) তবে ইন্টারফেসের জন্য এটি আরও শক্ত। একটি শ্রেণীর জন্য কোড এখানে:

using System;
using System.Collections.Generic;
using System.Reflection;

class Test
{
    static bool IsInstanceOfGenericType(Type genericType, object instance)
    {
        Type type = instance.GetType();
        while (type != null)
        {
            if (type.IsGenericType &&
                type.GetGenericTypeDefinition() == genericType)
            {
                return true;
            }
            type = type.BaseType;
        }
        return false;
    }

    static void Main(string[] args)
    {
        // True
        Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
                                                  new List<string>()));
        // False
        Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
                                                  new string[0]));
        // True
        Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
                                                  new SubList()));
        // True
        Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
                                                  new SubList<int>()));
    }

    class SubList : List<string>
    {
    }

    class SubList<T> : List<T>
    {
    }
}

সম্পাদনা: মন্তব্যগুলিতে উল্লিখিত হিসাবে, এটি ইন্টারফেসের জন্য কাজ করতে পারে:

foreach (var i in type.GetInterfaces())
{
    if (i.IsGenericType && i.GetGenericTypeDefinition() == genericType)
    {
        return true;
    }
}

আমার আশেপাশে কিছু বিশ্রী প্রান্তের মামলা থাকতে পারে এমন সন্দেহ আমার কাছে আছে তবে আমি এখনই এটি ব্যর্থ হতে পারি না।


2
সবেমাত্র এটি নিয়ে একটি সমস্যা আবিষ্কার হয়েছে। এটি উত্তরাধিকারের একক লাইনে চলে যায়। যদি, পথে, আপনার একটি বেস বর্গ এবং আপনি যে ইন্টারফেসটি সন্ধান করছেন উভয়ের সাথেই একটি বেস রয়েছে তবে এটি কেবল শ্রেণির পথেই যায়।
গ্রুমিক্স

1
@ গ্রাওক্সিক্স: সত্য। আমি সবেমাত্র স্পষ্ট করে দিয়েছি যে আমি উত্তরে এটি উল্লেখ করেছি যদিও: "জেনেরিক ধরণের যদি একটি শ্রেণি হয় তবে এটি খুব খারাপ নয় (যেমন এটি এই ক্ষেত্রে রয়েছে) তবে ইন্টারফেসের জন্য এটি আরও কঠিন। এখানে একটি শ্রেণীর কোড রয়েছে"
জন স্কেটি

1
আপনার কাছে <T> জানার উপায় না থাকলে কী হবে? পছন্দ করুন, এটি ইনট বা স্ট্রিং হতে পারে তবে আপনি এটি জানেন না। এটি উত্পন্ন হয়, এটি মিথ্যা negativeণাত্মক বলে মনে হচ্ছে ... সুতরাং আপনার ব্যবহার করার জন্য টি নেই, আপনি কেবল কিছু বস্তুর বৈশিষ্ট্য অনুসন্ধান করছেন এবং একটি হ'ল একটি তালিকা। আপনি কীভাবে জানবেন যে এটি একটি তালিকা যাতে আপনি এটি আনপিল করতে পারেন? এর অর্থ আমার, আপনার কাছে কোথাও টি নেই বা ব্যবহারের মতো প্রকার নেই। আপনি প্রতিটি ধরণের অনুমান করতে পারেন (এটি তালিকা <তালিকা>? এটি তালিকা <স্ট্রিং>?) তবে আপনি যা জানতে চান সেটি কি এই এএ তালিকাভুক্ত? এই প্রশ্নের উত্তর দেওয়া কঠিন বলে মনে হচ্ছে।

@RiverC: হ্যাঁ, আপনি ঠিক - এটি হল , উত্তর করা মোটামুটি কঠিন বিভিন্ন কারণের জন্য। আপনি যদি কেবল একটি শ্রেণীর কথা বলছেন তবে এটি খুব খারাপ নয় ... আপনি উত্তরাধিকারী গাছটি চালিয়ে যেতে পারেন এবং List<T>আপনি কোনও আকারে বা অন্যভাবে আঘাত করেছেন কিনা তা দেখতে পারেন । আপনি যদি ইন্টারফেস অন্তর্ভুক্ত করেন, এটি সত্যই জটিল।
জন স্কিটি

3
সমতা অপারেটর ( ) এর পরিবর্তে IsInstanceOfGenericTypeআপনি কোনও কল দিয়ে লুপটি প্রতিস্থাপন করতে পারবেন না ? IsAssignableFrom==
স্ল্যাভকউইন

7

আপনি ডায়নামিক অ্যালথৌথ ব্যবহার করে সংক্ষিপ্ত কোডটি ব্যবহার করতে পারেন এটি খাঁটি প্রতিবিম্বের চেয়ে ধীর হতে পারে:

public static class Extension
{
    public static bool IsGenericList(this object o)
    {
       return IsGeneric((dynamic)o);
    }

    public static bool IsGeneric<T>(List<T> o)
    {
       return true;
    }

    public static bool IsGeneric( object o)
    {
        return false;
    }
}



var l = new List<int>();
l.IsGenericList().Should().BeTrue();

var o = new object();
o.IsGenericList().Should().BeFalse();

7

এগুলি আমার দুটি পছন্দসই এক্সটেনশন পদ্ধতি যা জেনেরিক ধরণের চেকিংয়ের সর্বাধিক প্রান্তের কেসগুলি কভার করে:

সঙ্গে কাজ করে:

  • একাধিক (জেনেরিক) ইন্টারফেস
  • একাধিক (জেনেরিক) বেস ক্লাস
  • একটি ওভারলোড রয়েছে যা নির্দিষ্ট জেনেরিক প্রকারটি সত্য হয়ে গেলে 'আউট' করবে (নমুনাগুলির জন্য ইউনিট পরীক্ষা দেখুন):

    public static bool IsOfGenericType(this Type typeToCheck, Type genericType)
    {
        Type concreteType;
        return typeToCheck.IsOfGenericType(genericType, out concreteType); 
    }
    
    public static bool IsOfGenericType(this Type typeToCheck, Type genericType, out Type concreteGenericType)
    {
        while (true)
        {
            concreteGenericType = null;
    
            if (genericType == null)
                throw new ArgumentNullException(nameof(genericType));
    
            if (!genericType.IsGenericTypeDefinition)
                throw new ArgumentException("The definition needs to be a GenericTypeDefinition", nameof(genericType));
    
            if (typeToCheck == null || typeToCheck == typeof(object))
                return false;
    
            if (typeToCheck == genericType)
            {
                concreteGenericType = typeToCheck;
                return true;
            }
    
            if ((typeToCheck.IsGenericType ? typeToCheck.GetGenericTypeDefinition() : typeToCheck) == genericType)
            {
                concreteGenericType = typeToCheck;
                return true;
            }
    
            if (genericType.IsInterface)
                foreach (var i in typeToCheck.GetInterfaces())
                    if (i.IsOfGenericType(genericType, out concreteGenericType))
                        return true;
    
            typeToCheck = typeToCheck.BaseType;
        }
    }

(প্রাথমিক) কার্যকারিতাটি প্রদর্শন করার জন্য এখানে একটি পরীক্ষা দেওয়া হয়েছে:

 [Test]
    public void SimpleGenericInterfaces()
    {
        Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IEnumerable<>)));
        Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IQueryable<>)));

        Type concreteType;
        Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IEnumerable<>), out concreteType));
        Assert.AreEqual(typeof(IEnumerable<string>), concreteType);

        Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IQueryable<>), out concreteType));
        Assert.AreEqual(typeof(IQueryable<string>), concreteType);


    }

0
return list.GetType().IsGenericType;

3
এটি একটি ভিন্ন প্রশ্নের জন্য সঠিক। এই প্রশ্নের জন্য, এটি ভুল, কারণ এটি কেবল সমস্যার অর্ধেকের চেয়ে (উল্লেখযোগ্যভাবে কম) সম্বোধন করে।
গ্রোক্সিক্স

1
স্ট্যান আর এর উত্তর প্রশ্ন যেমন যাকে জাহির, কিন্তু কি ওপি সত্যিই বোঝানো ছিল "টেস্টিং যদি বস্তুর একটি হল সত্য উত্তর নেই বিশেষ C # জেনেরিক প্রকার", যার জন্য এই উত্তর প্রকৃতপক্ষে অসম্পূর্ণ।
yoyo

লোকেরা আমাকে নিচে ভোট দিচ্ছে কারণ আমি "জেনেরিক ধরণের" এর চেয়ে "জেনেরিক ধরণের" এর প্রসঙ্গে প্রশ্নের উত্তর দিয়েছি। ইংরেজি আমার দ্বিতীয় ভাষা এবং এ জাতীয় ভাষার ঘনত্বগুলি আমাকে প্রায়শই পাস করে দেয়, আমার প্রতিরক্ষায় ওপি নির্দিষ্টভাবে কোনও নির্দিষ্ট ধরণের বিরুদ্ধে পরীক্ষা করতে বলে না এবং শিরোনামে "জেনেরিক টাইপের" হয় তা নিশ্চিত না ... কেন আমি নিম্নস্তরের প্রাপ্য? একটি অস্পষ্ট প্রশ্ন
স্ট্যান আর

2
এখন আপনি এটি জানেন এবং আপনি আরও নির্দিষ্ট এবং সঠিক হওয়ার জন্য নিজের উত্তরকে উন্নত করতে পারেন।
পিটার ইভান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.