স্থিতিশীল পদ্ধতি একটি উদাহরণ পদ্ধতি কল করে কেন সি # সংকলকটি ত্রুটি কোড নয়?


110

নিম্নলিখিত কোডটিতে একটি স্ট্যাটিক পদ্ধতি রয়েছে, Foo()একটি উদাহরণ পদ্ধতি কল করে Bar():

public sealed class Example
{
    int count;

    public static void Foo( dynamic x )
    {
        Bar(x);
    }

    void Bar( dynamic x )
    {
        count++;
    }
}

এটি ত্রুটি * ছাড়াই সংকলন করে তবে রানটাইমটিতে একটি রানটাইম বাইন্ডার ব্যতিক্রম উত্পন্ন করে। এই পদ্ধতিগুলিতে গতিশীল পরামিতি অপসারণ করা প্রত্যাশার মতো একটি সংকলক ত্রুটির কারণ হয়ে থাকে।

তাহলে কেন ডায়নামিক প্যারামিটার থাকার কারণে কোডটি সংকলিত হতে দেওয়া হয়? রিশার্পার এটিকে ত্রুটি হিসাবে দেখায় না।

সম্পাদনা 1: * ভিজ্যুয়াল স্টুডিও ২০০৮ এ

সম্পাদনা 2:sealed একটি সাবক্লাসে একটি স্ট্যাটিক Bar(...)পদ্ধতি থাকতে পারে বলে এটি সম্ভবত যুক্ত করা হয়েছে । এমনকি সিল করা সংস্করণটি সংকলিত হয় যখন রানটাইম সময়ে উদাহরণ পদ্ধতি ব্যতীত অন্য কোনও পদ্ধতি কল করা সম্ভব হয় না।


8
খুব ভাল প্রশ্নের জন্য +1
কুওঙ্গল

40
এটি একটি এরিক-লিপার্ট-প্রশ্ন।
অলিভিয়ার জ্যাকট-ডেসকোম্বেস

3
আমি দৃ sure়ভাবে নিশ্চিত যে জোন স্কিটি এই আসল সাথে কী করতে হবে তা জানতে পারে;) @ অলিভিয়ার জাকোট-ডেসকোম্বেস
হাজার

2
@ অলিভিয়ার, জন স্কিটি সম্ভবত কোডটি সংকলন করতে চেয়েছিলেন, তাই সংকলক এটির অনুমতি দেয় :-))
মাইক স্কট

5
এটি dynamicসত্যই আপনার প্রয়োজন না হলে কেন আপনার ব্যবহার করা উচিত নয় এটির আরও একটি উদাহরণ ।
11:30

উত্তর:


71

আপডেট: নীচে উত্তরটি সি # 7.3 (মে 2018) এর আগে 2012 সালে লেখা হয়েছিল । ইন কি C # এর 7.3 এ নতুন , বিভাগ উন্নত জমিদার প্রার্থীদের , আইটেম 1, এটি ব্যাখ্যা করা হয় কিভাবে জমিদার রেজল্যুশন নিয়ম তাই পরিবর্তিত অ স্ট্যাটিক overloads গোড়ার দিকে বাতিল করা হয়। সুতরাং নীচের উত্তর (এবং এই পুরো প্রশ্ন) এখনই বেশিরভাগই কেবল historicalতিহাসিক আগ্রহ!


(প্রাক সি # 7.3 :)

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

class SillyStuff
{
  static void SameName(object o) { }
  void SameName(string s) { }

  public static void Test()
  {
    SameName("Hi mom");
  }
}

এটি সংকলন করবে না কারণ সেরা ওভারলোড হ'ল এটি string। তবে ওহে, এটি একটি উদাহরণ পদ্ধতি, তাই সংকলক অভিযোগ করেন (দ্বিতীয় সেরা ওভারলোড নেওয়ার পরিবর্তে)।

সংযোজন: সুতরাং আমি মনে করি dynamicমূল প্রশ্নের উদাহরণের ব্যাখ্যাটি হ'ল ধারাবাহিক হওয়ার জন্য, প্রকারগুলি গতিশীল হলে আমরা প্রথমে সেরা ওভারলোডও খুঁজে পাই (কেবলমাত্র প্যারামিটার সংখ্যা এবং প্যারামিটারের পরীক্ষা করা ইত্যাদি), স্থির বনাম নয় not -স্ট্যাটিক), এবং কেবল তখনই স্থির জন্য পরীক্ষা করুন। তবে এর অর্থ স্ট্যাটিক চেকটি রানটাইম পর্যন্ত অপেক্ষা করতে হবে। সুতরাং পর্যবেক্ষণ আচরণ।

দেরিতে সংযোজন: তারা কেন এই মজাদার আদেশটি কিছু করতে বেছে নিয়েছে তার কিছু পটভূমি এরিক লিপার্টের এই ব্লগ পোস্ট থেকে অনুমান করা যায় ।


মূল প্রশ্নে কোনও ওভারলোড নেই। স্ট্যাটিক ওভারলোড দেখানো উত্তরগুলি প্রাসঙ্গিক নয়। "আপনি যদি এটি লিখেন ভাল ..." এর উত্তর দেওয়া বৈধ নয় কারণ আমি এটি লিখিনি :-)
মাইক স্কট

5
@ মাইকস্কট আমি কেবল আপনাকে বোঝানোর চেষ্টা করি যে সি # তে ওভারলোড রেজোলিউশন সর্বদা এরকম হয়: (1) স্ট্যাটিক / অ-স্থিতিশীল উপেক্ষা করে সেরা ম্যাচটি সন্ধান করুন। (২) এখন আমরা জানি কী কী ওভারলোড ব্যবহার করতে হবে, তারপরে স্থির জন্য পরীক্ষা করুন। এ কারণে, যখন dynamicভাষায় পরিচয় করানো হয়েছিল , তখন আমার মনে হয় সি # এর ডিজাইনাররা বলেছেন: "আমরা (2) সংকলন-সময়টি যখন এটি dynamicপ্রকাশ করি তখন বিবেচনা করব না ।" সুতরাং আমার উদ্দেশ্য এখানে এই ধারণাটি নিয়ে আসে যে তারা রানটাইম পর্যন্ত স্ট্যাটিক বনাম উদাহরণটি পরীক্ষা না করা কেন বেছে নিয়েছিল। আমি বলব, এই চেকটি বাইন্ডিং সময়ে হয়
জেপ্পে স্টিগ নীলসন

যথেষ্ট ন্যায্য তবে এটি এখনও ব্যাখ্যা করে না যে কেন এই ক্ষেত্রে সংকলক উদাহরণ পদ্ধতিতে কলটি সমাধান করতে পারে না। অন্য কথায়, সংকলকটি যেভাবে রেজোলিউশনটি করে তা সরল - এটি আমার উদাহরণের মতো সরল কেসটিকে স্বীকৃতি দেয় না যেখানে কলটি সমাধান করতে পারে না এমন কোনও সম্ভাবনা নেই। বিড়ম্বনাটি হ'ল: ডায়নামিক প্যারামিটার সহ একটি বার () পদ্ধতি থাকার পরে, সংকলকটি সেই একক বার () পদ্ধতিটিকে উপেক্ষা করে।
মাইক স্কট

45
আমি সি # সংকলকের এই অংশটি লিখেছি এবং জেপ্পে ঠিক বলেছেন। দয়া করে এটিকে ভোট দিন। ওভারলোড রেজোলিউশনটি প্রদত্ত পদ্ধতিটি স্থিতিশীল বা কোনও উদাহরণ পদ্ধতি কিনা তা যাচাই করার আগে ঘটে এবং এই ক্ষেত্রে আমরা ওভারলোড রেজোলিউশনটিকে রানটাইম পর্যন্ত স্থির করি এবং সুতরাং রানটাইম পর্যন্ত স্থিতিক / উদাহরণ চেকও করি। অতিরিক্তভাবে, সংকলক স্থিতিশীলভাবে গতিশীল ত্রুটিগুলি খুঁজে পেতে একটি "সর্বোত্তম প্রচেষ্টা" রাখে যা একেবারেই বিস্তৃত নয়।
ক্রিস বুড়ো

30

ফু এর একটি প্যারামিটার রয়েছে "এক্স" যা গতিশীল, যার অর্থ বার (এক্স) একটি গতিশীল এক্সপ্রেশন।

উদাহরণের জন্য যেমন পদ্ধতি রয়েছে এটি পুরোপুরি সম্ভব হবে:

static Bar(SomeType obj)

কোন ক্ষেত্রে সঠিক পদ্ধতি সমাধান করা হবে, সুতরাং বার (এক্স) স্টেটমেন্টটি পুরোপুরি বৈধ। দৃষ্টান্ত পদ্ধতি বার (x) রয়েছে তা বাস্তবায়নহীন এবং এমনকি বিবেচনা করা হয় না: সংজ্ঞা অনুসারে , বার (এক্স) যেহেতু একটি গতিশীল অভিব্যক্তি, তাই আমাদের রানটাইমের স্থগিতিত রেজোলিউশন রয়েছে।


14
তবে আপনি যখন দৃষ্টান্ত বার পদ্ধতিটি বের করেন, এটি আর সংকলন করে না।
জাস্টিন হার্ভে

1
@ জাস্টিন আকর্ষণীয় - একটি সতর্কতা? নাকি ত্রুটি? যে কোনও উপায়ে, এটি পুরোপুরি ওভারলোড রেজোলিউশনটি রানটাইমে রেখে কেবল পদ্ধতি-গোষ্ঠী হিসাবেই বৈধ হতে পারে।
মার্ক গ্র্যাভেল

1
@ মার্ক, যেহেতু অন্য বার () পদ্ধতি নেই, আপনি প্রশ্নের উত্তর দিচ্ছেন না। আপনি কি বোঝাতে পারেন যে কেবলমাত্র একটি ওভারলোড ছাড়াই একটি বার () পদ্ধতি রয়েছে? অন্য কোনও পদ্ধতি কল করার উপায় নেই যখন রানটাইম স্থগিত কেন? নাকি আছে? দ্রষ্টব্য: আমি ক্লাসটি সিল করার জন্য কোডটি সম্পাদনা করেছি, যা এখনও সংকলন করে।
মাইক স্কট

1
@ রানটাইম কেন স্থগিত করা উচিত তা মেনে চলুন: কারণ ডাইনামিকের অর্থ
মার্ক গ্র্যাভেল

2
@ মাইকে অসম্ভব বলে মনে হচ্ছে না; যা গুরুত্বপূর্ণ তা হ'ল এটি প্রয়োজনীয় কিনা । ডায়নামিকের সাথে পুরো বিষয়টিটি হ'ল এটি কম্পাইলারের কাজ নয়।
মার্ক গ্র্যাভেল

9

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

"ডান" পদ্ধতিটি রানটাইমের সময় নির্ধারিত হবে। সংকলকটি রানটাইম চলাকালীন সেখানে কোনও বৈধ পদ্ধতি আছে কিনা তা জানতে পারে না।

"ডায়নামিক" কীওয়ার্ডটি গতিশীল এবং স্ক্রিপ্ট ভাষার জন্য সংজ্ঞায়িত করা হয়, যেখানে পদ্ধতিটি যে কোনও সময় সংজ্ঞায়িত করা যায় এমনকি রানটাইমের সময়কালেও। ক্রেজি স্টাফ

এখানে একটি নমুনা যা ইনট পরিচালনা করে তবে কোন স্ট্রিং নেই, কারণ পদ্ধতিটির কারণ রয়েছে।

class Program {
    static void Main(string[] args) {
        Example.Foo(1234);
        Example.Foo("1234");
    }
}
public class Example {
    int count;

    public static void Foo(dynamic x) {
        Bar(x);
    }

    public static void Bar(int a) {
        Console.WriteLine(a);
    }

    void Bar(dynamic x) {
        count++;
    }
}

আপনি সমস্ত "ভুল" কলগুলি পরিচালনা করতে একটি পদ্ধতি যুক্ত করতে পারেন, যা পরিচালনা করা যায়নি

public class Example {
    int count;

    public static void Foo(dynamic x) {
        Bar(x);
    }

    public static void Bar<T>(T a) {
        Console.WriteLine("Error handling:" + a);
    }

    public static void Bar(int a) {
        Console.WriteLine(a);
    }

    void Bar(dynamic x) {
        count++;
    }
}

আপনার উদাহরণে কলিং কোডটি উদাহরণ.ফু (...) এর পরিবর্তে উদাহরণ.বার (...) হওয়া উচিত নয়? আপনার উদাহরণে কি ফু () অপ্রাসঙ্গিক নয়? আমি সত্যিই আপনার উদাহরণ বুঝতে পারি না। স্থির জেনেরিক পদ্ধতি যুক্ত করা কেন সমস্যার কারণ হবে? বিকল্পটি না দেওয়ার পরিবর্তে আপনি কি নিজের উত্তরটি সম্পাদন করতে পারবেন?
মাইক স্কট

তবে আমি যে উদাহরণটি পোস্ট করেছি তাতে কেবল একটি একক উদাহরণ পদ্ধতি রয়েছে এবং কোনও ওভারলোড নেই তাই সংকলনের সময় আপনি জানেন যে কোনও সম্ভাব্য স্থির পদ্ধতি নেই যা সমাধান করা যেতে পারে। আপনি যদি অন্তত একটি যোগ করেন তবেই পরিস্থিতি পরিবর্তন হয় এবং কোডটি বৈধ।
মাইক স্কট

তবে এই উদাহরণটিতে এখনও একাধিক বার () পদ্ধতি রয়েছে। আমার উদাহরণের একটি মাত্র পদ্ধতি আছে। সুতরাং কোনও স্ট্যাটিক বার () পদ্ধতি কল করার কোনও সম্ভাবনা নেই। সংকলন সময়ে কলটি সমাধান করা যেতে পারে।
মাইক স্কট

@ মাইক হতে পারে! = হয়; গতিশীল সহ, এটি করার প্রয়োজন নেই
মার্ক গ্র্যাভেল

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