। নেট: স্থির পদ্ধতিতে "এই" শ্রেণীর ধরণ নির্ধারণ করুন


97

একটি অ স্থির পদ্ধতিতে আমি ব্যবহার করতে পারি this.GetType()এবং এটিটি ফিরে আসত TypeTypeস্থির পদ্ধতিতে আমি কীভাবে এটি পেতে পারি ? অবশ্যই, আমি কেবল লিখতে পারি না typeof(ThisTypeName)কারণ ThisTypeNameএটি কেবল রানটাইমে পরিচিত। ধন্যবাদ!


16
আপনি স্থিতিশীল প্রসঙ্গে আছেন এবং টাইপফ (এটি টাইপনাম) লিখতে পারবেন না? কীভাবে?
ব্রুনো রিস

4
কোনও স্ট্যাটিক পদ্ধতির ভিতরে 'রানটাইম' এর মতো কিছুই নেই (ধরে নিই যে আপনি কোনও স্ট্যাটিক পদ্ধতিতে পাস হওয়া কোনও যুক্তির কথা বলছেন না)। সেক্ষেত্রে আপনি কেবল টাইপফ (রিলেভেন্টটাইপ) বলতে পারেন।
মনিশ বসন্তানী

4
একটি স্ট্যাটিক পদ্ধতি ভার্চুয়াল হতে পারে না। আপনি ইতিমধ্যে টাইপ জানেন।
হ্যানস প্যাস্যান্ট

7
একটি বিমূর্ত থেকে অনেক উত্পন্ন ক্লাস থাকবে। বেস বিমূর্ত শ্রেণীর স্থিতিশীল অভিধান রয়েছে <আন্ত, টাইপ>। স্ট্যাটিক কনস্ট্রাক্টরে (ডিক.এড যোগ করুন (এন, টি)) নিজেই ক্লাসগুলি "নিবন্ধন করুন" থেকে উত্পন্ন। এবং হ্যাঁ, আমি টাইপটি জানি না :) আমি কিছুটা অলস এবং পাঠ্যটি প্রতিস্থাপন করতে পছন্দ করি না এবং ভাবছিলাম যে রানটাইমে "টি" নির্ধারণ করা যায় কিনা। দয়া করে আমার মিথ্যাটি ক্ষমা করুন, কারণ এটি কেবল প্রশ্নটি সরল করার প্রয়োজন ছিল। এবং এটি কাজ করেছে;) এখন একটি গ্রহণযোগ্য সমাধান রয়েছে। ধন্যবাদ
ইয়েগোর

একটি সাবক্লাস তার সুপারক্লাসের স্থির পদ্ধতি উত্তরাধিকার সূত্রে প্রাপ্ত, না? সুপারক্লাস স্ট্যাটিক পদ্ধতিটি এর সমস্ত উপ-শ্রেণীর জন্য কার্যকর হওয়ার জন্য কী বোঝায় না? স্ট্যাটিকের সহজ অর্থ একটি উদাহরণ ছাড়াই, অবশ্যই একটি সাধারণ বেস শ্রেণিতে সাধারণ কোডের নীতিটি স্ট্যাটিক পদ্ধতিগুলির পাশাপাশি উদাহরণের পদ্ধতিতেও প্রযোজ্য?
ম্যাট কনলি

উত্তর:


136

আপনি যদি this.GetType()স্থির পদ্ধতির সমতুল্য 1 টি লাইনার সন্ধান করেন তবে নীচের চেষ্টা করুন।

Type t = MethodBase.GetCurrentMethod().DeclaringType

যদিও এটি সম্ভবত ব্যবহারের চেয়ে অনেক বেশি ব্যয়বহুল typeof(TheTypeName)


4
এই এক ভাল কাজ করে। ধন্যবাদ :) এটি এত ব্যয়বহুল নয় কারণ এটি বেশ বিরল বলা হবে।
ইয়েগোর

4
"ব্যয়বহুল" জ্যারেড দ্বারা প্রবেশের অর্থ, প্রসেসরের জন্য এগুলি ব্যয়বহুল, সাধারণত ধীর অর্থ। তবে তিনি বলেছিলেন, "অনেক বেশি ব্যয়বহুল" অর্থ ধীর। আপনি কোনও রকেট-গাইডেন্স সিস্টেম ডিজাইন না করা পর্যন্ত সম্ভবত কিছুটা ধীরে চলবে না।
ড্যান রোজনস্টার্ক

4
আমি দেখেছি গেটকারেন্টমথোড কিছু গুরুতর পারফরম্যান্স সমস্যার কারণ হতে পারে। তবে যেহেতু আপনি কেবল টাইপ পাচ্ছেন আপনি এটি ক্যাশে করতে পারেন।
জোনাথন অ্যালেন

52
এটি সর্বদা ক্লাসটি ফিরিয়ে দেয় যা বর্তমান পদ্ধতি প্রয়োগ করে, সাবক্লাসের ক্ষেত্রে যে শ্রেণিকে ডাকা হত তা নয়।
ম্যাট কনলি

4
আমার ধারণা, কোডটি যদি কখনও বিভিন্ন শ্রেণীর নাম বা typeof(TheTypeName)কোনও কিছুর কাছে স্থানান্তরিত হয় তবে ত্রুটিগুলি এড়ানো সহজ but
নাইয়ারগডস

59

এমন কিছু আছে যা অন্যান্য উত্তরগুলি বেশ পরিষ্কারভাবে ব্যাখ্যা করতে পারে নি, এবং যা প্রকারের সময় কেবলমাত্র টাইপ পাওয়া যায় সে সম্পর্কে আপনার ধারণার সাথে প্রাসঙ্গিক।

আপনি যদি কোনও স্থিতিশীল সদস্যকে কার্যকর করতে কোনও ডাইরেক্টেড প্রকার ব্যবহার করেন তবে আসল টাইপের নাম বাইনারিটিতে বাদ দেওয়া হবে। সুতরাং উদাহরণস্বরূপ, এই কোডটি সংকলন করুন:

UnicodeEncoding.GetEncoding(0);

এখন এটিতে ইলডਜ਼ਮ ব্যবহার করুন ... আপনি দেখতে পাবেন যে কলটি এইভাবে নির্গত হয়েছিল:

IL_0002:  call       class [mscorlib]System.Text.Encoding 
[mscorlib]System.Text.Encoding::GetEncoding(int32)

সংকলকটি কলটি সমাধান করেছে Encoding.GetEncoding- UnicodeEncodingবামের কোনও সন্ধান নেই । এটি আপনার "বর্তমান ধরণের" ধারণাটি অযৌক্তিক করে তোলে, আমি ভয় করি।


দ্রুত এগিয়ে 10 বছর এবং কেন এখনও সি # তে ভার্চুয়াল স্ট্যাটিকস নেই? ;) সাধারণত তাদের প্রয়োজন হয় না ... তবে বিরল
ঘটনাগুলি

@ মার্চেওয়েক: খুব, খুব বিরল আমি বলব - সি বিরল টিম সবসময় আরও দরকারী জিনিস খুঁজে পেতে পারে। (তারা এই পুরো সময় অলস থাকার মতো নয় ...)
জন স্কিটি

24

আরেকটি সমাধান হ'ল একটি স্বাবলম্বী প্রকার ব্যবহার করা

//My base class
//I add a type to my base class use that in the static method to check the type of the caller.
public class Parent<TSelfReferenceType>
{
    public static Type GetType()
    {
        return typeof(TSelfReferenceType);
    }
}

তারপরে যে বর্গটি উত্তরাধিকারসূত্রে আসে, আমি স্ব-রেফারেন্সিং টাইপটি তৈরি করি:

public class Child: Parent<Child>
{
}

এখন প্যারেন্টের অভ্যন্তরে কল টাইপ অফ (টিএসএলএফআরফারেন্সটাইপ) কলকারীর প্রকারটি পাবেন এবং কোনও উদাহরণের প্রয়োজন ছাড়াই কল করুন return

Child.GetType();

-রব


আমি এটি সিঙ্গলটন নিদর্শনগুলির জন্য ব্যবহার করেছি, যেমন সিঙ্গেলটন <T> ... স্থির সদস্যরা ত্রুটি বার্তাগুলিতে বা অন্য যেখানে প্রয়োজন সেখানে টাইপফ (টি) উল্লেখ করতে পারেন।
yoyo

4
ওহে. আমি এই উত্তরটি সত্যিই পছন্দ করি এবং প্রশংসা করি কারণ এটি একটি স্ট্যাটিক বেস ফাংশন থেকে সন্তানের ধরণের সন্ধানের জন্য আমাকে একটি পরিশ্রম দেয়।
বিল সফটওয়্যার ইঞ্জিনিয়ার

4
সুন্দর. খুব দুঃখের বিষয় যে সি # তে যদিও এই ছোট কোডের সদৃশতা ছাড়া এটি করা যায় না।
প্রদর্শিত নাম


উভয় (এটি এবং স্টিভেনের সাথে সংযুক্ত একটি) বেস শ্রেণীর প্রয়োগকারীদের উত্তরাধিকারীদের জন্য কাজ করবে না ... নাতি
নাতনিরা

5

আপনি thisএকটি স্থিতিশীল পদ্ধতিতে ব্যবহার করতে পারবেন না , সুতরাং এটি সরাসরি সম্ভব নয়। যাইহোক, যদি আপনার কোনও বস্তুর প্রকারের প্রয়োজন হয় তবে কেবল GetTypeএটির কল করুন এবং thisউদাহরণটি আপনাকে একটি প্যারামিটার তৈরি করুন , যেমন:

public class Car {
  public static void Drive(Car c) {
    Console.WriteLine("Driving a {0}", c.GetType());
  }
}

যদিও এটি একটি দুর্বল নকশার মতো মনে হচ্ছে। আপনি কি নিশ্চিত যে আপনার নিজের স্ট্যাটিক পদ্ধতির অভ্যন্তরে উদাহরণটির ধরণটি সত্যই পাওয়া দরকার? মনে হচ্ছে একটু উদ্ভট। কেন শুধু একটি উদাহরণ পদ্ধতি ব্যবহার করবেন না?

public class Car {
  public void Drive() { // Remove parameter; doesn't need to be static.
    Console.WriteLine("Driving a {0}", this.GetType());
  }
}

3

আপনি কেন টাইপফ (এই টাইপনাম) ব্যবহার করতে পারবেন না তা আমি বুঝতে পারি না। যদি এটি একটি জেনেরিক প্রকারের হয় তবে এটি ব্যবহার করা উচিত:

class Foo {
   static void Method1 () {
      Type t = typeof (Foo); // Can just hard code this
   }
}

এটি যদি জেনেরিক ধরণের হয় তবে:

class Foo<T> {
    static void Method1 () {
       Type t = typeof (Foo<T>);
    }
}

আমি কি এখানে স্পষ্ট কিছু মিস করছি?


7
আপনি যদি ফু থেকে প্রাপ্ত ক্লাস বার তৈরি করেন এবং ক্লাসটি মেথড 1 এর উত্তরাধিকারী হয় তবে এটি কাজ করবে না - তারপরে বার.মথোদ 1 এ কল এখনও টাইপফ (ফু) প্রক্রিয়াকরণ করবে যা ভুল। উত্তরাধিকার সূত্রে প্রাপ্ত পদ্ধতিটি কোনওভাবে জানতে হবে যে এটি বারে চালিত হয়েছে এবং তারপরে টাইপ অফ (বার) পান।
জাস্টামার্টিন

0

যখন আপনার সদস্য অবিচল থাকে, আপনি সর্বদা জানবেন যে রানটাইমের সময় এটি কোন ধরণের অংশ। এক্ষেত্রে:

class A
{
  public static int GetInt(){}

}
class B : A {}

আপনি কল করতে পারবেন না (সম্পাদনা করুন: আপাতদৃষ্টিতে, আপনি নীচের মন্তব্য দেখতে পারেন, তবে আপনি এখনও এ-তে কল করবেন):

B.GetInt();

সদস্য অবিচলিত হওয়ার কারণে এটি উত্তরাধিকারের পরিস্থিতিতে অংশ নেয় না। কিন্তু, আপনি সর্বদা জানেন যে টাইপটি এ।


4
আপনি B.GetInt () কে কল করতে পারেন - কমপক্ষে, আপনি এটি ব্যক্তিগত না থাকলেও করতে পারেন - তবে সংকলন এটি এ.গেটইন্ট () এ একটি কলটিতে অনুবাদ করবে। চেষ্টা করে দেখুন!
জন স্কিটি

জনের মন্তব্যে দ্রষ্টব্য: সি # তে ডিফল্ট দৃশ্যমানতা ব্যক্তিগত, সুতরাং আপনার উদাহরণটি কার্যকর হয় না।
ড্যান রোজেনস্টার্ক

0

আমার উদ্দেশ্যে, আমি @ টি-মোটির ধারণা পছন্দ করি। যদিও আমি বছরের পর বছর ধরে "স্ব-রেফারেন্সিং ধরণের" তথ্য ব্যবহার করেছি, বেস ক্লাসের রেফারেন্স পরে করা আরও কঠিন।

উদাহরণস্বরূপ (উপরে থেকে @ রব লেক্লার্ক উদাহরণ ব্যবহার করে):

public class ChildA: Parent<ChildA>
{
}

public class ChildB: Parent<ChildB>
{
}

এই নিদর্শনটির সাথে কাজ করা চ্যালেঞ্জিং হতে পারে, উদাহরণস্বরূপ; কোনও ফাংশন কল থেকে আপনি বেস ক্লাসটি কীভাবে ফিরে পাবেন?

public Parent<???> GetParent() {}

বা টাইপ কাস্টিং যখন?

var c = (Parent<???>) GetSomeParent();

সুতরাং, আমি যখন পারি তখন এটি এড়াতে চেষ্টা করি এবং যখন প্রয়োজন তখন এটি ব্যবহার করি। যদি আপনার অবশ্যই হয় তবে আমি আপনাকে এই প্যাটার্নটি অনুসরণ করার পরামর্শ দিচ্ছি:

class BaseClass
{
    // All non-derived class methods goes here...

    // For example:
    public int Id { get; private set; }
    public string Name { get; private set; }
    public void Run() {}
}

class BaseClass<TSelfReferenceType> : BaseClass
{
    // All derived class methods goes here...

    // For example:
    public TSelfReferenceType Foo() {}
    public void Bar(TSelfRefenceType obj) {}
}

এখন আপনি (আরও) সহজেই এর সাথে কাজ করতে পারেন BaseClass। যাইহোক, আমার বর্তমান পরিস্থিতিটির মতো সময় রয়েছে, যেখানে বেস বর্গের মধ্যে থেকে উত্পন্ন শ্রেণীর প্রকাশ করা প্রয়োজন হয় না এবং @ এম-মোতির পরামর্শটি ব্যবহার করা সঠিক পন্থা হতে পারে।

যাইহোক, @ এম-মোটির কোড ব্যবহার করা ততক্ষণ কাজ করবে যতক্ষণ না বেস ক্লাসে কল স্ট্যাকের কোনও ইনস্ট্যান্স কনস্ট্রাক্টর না থাকে। দুর্ভাগ্যক্রমে আমার বেস ক্লাসগুলি উদাহরণ নির্মাণকারী ব্যবহার করে।

অতএব, এখানে আমার বর্ধিত পদ্ধতিটি অ্যাকাউন্ট বেস শ্রেণীর 'উদাহরণস্বরূপ' নির্মাতাদের গ্রহণ করে:

public static class TypeExtensions
{
    public static Type GetDrivedType(this Type type, int maxSearchDepth = 10)
    {
        if (maxSearchDepth < 0)
            throw new ArgumentOutOfRangeException(nameof(maxSearchDepth), "Must be greater than 0.");

        const int skipFrames = 2;  // Skip the call to self, skip the call to the static Ctor.
        var stack = new StackTrace();
        var maxCount = Math.Min(maxSearchDepth + skipFrames + 1, stack.FrameCount);
        var frame = skipFrames;

        // Skip all the base class 'instance' ctor calls. 
        //
        while (frame < maxCount)
        {
            var method = stack.GetFrame(frame).GetMethod();
            var declaringType = method.DeclaringType;

            if (type.IsAssignableFrom(declaringType))
                return declaringType;

            frame++;
        }

        return null;
    }
}

0

সম্পাদনা করুন এই পদ্ধতিগুলি কেবল তখনই কার্যকর হবে যখন আপনি পিডিবি ফাইলগুলি এক্সিকিউটেবল / লাইব্রেরির সাথে মার্কম্নল হিসাবে স্থাপন করবেন আমার দিকে ইঙ্গিত ।

অন্যথায় এটি শনাক্ত করার জন্য একটি বিশাল সমস্যা হবে: বিকাশে ভাল কাজ করে, তবে সম্ভবত উত্পাদন হয় না।


ইউটিলিটি পদ্ধতি, আপনার কোডের প্রতিটি জায়গা থেকে আপনার প্রয়োজন হলে কেবল পদ্ধতিটি কল করুন:

public static Type GetType()
{
    var stack = new System.Diagnostics.StackTrace();

    if (stack.FrameCount < 2)
        return null;

    return (stack.GetFrame(1).GetMethod() as System.Reflection.MethodInfo).DeclaringType;
}

4
স্ট্যাকট্রেস কেবলমাত্র ডিবাগ বিল্ডগুলিতে উপলভ্য
মার্কম্নল

সঠিক নয়: আপনি যখন রিলিজ মোডে .pdb ফাইলগুলি স্থাপন করেন তখন স্ট্যাকট্রেস উপলব্ধ হবে। stackoverflow.com/questions/2345957/...
টি-moty

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