আমি সি # তে জেনেরিক পদ্ধতি থেকে কীভাবে নুল ফিরিয়ে দিতে পারি?


546

এই (ডামি) কোডটি সহ আমার একটি জেনেরিক পদ্ধতি রয়েছে (হ্যাঁ আমি অবগত আছি আইলিস্টের পূর্বাভাস রয়েছে, তবে আমার কোডটি আইলিস্ট ব্যবহার করছে না তবে অন্য কিছু সংগ্রহ করছে, যাইহোক এটি প্রশ্নের অপ্রাসঙ্গিক ...)

static T FindThing<T>(IList collection, int id) where T : IThing, new()
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;  // ERROR: Cannot convert null to type parameter 'T' because it could be a value type. Consider using 'default(T)' instead.
}

এটি আমাকে একটি বিল্ড ত্রুটি দেয়

"নালকে প্যারামিটার 'টি' টাইপ করতে রূপান্তর করতে পারে না কারণ এটি একটি মান ধরণের হতে পারে instead পরিবর্তে 'ডিফল্ট (টি)' ব্যবহারের কথা বিবেচনা করুন" "

আমি কি এই ত্রুটি এড়াতে পারি?


অযোগ্য রেফারেন্স টাইপগুলি (সি # 8 এ) এখন এর আরও ভাল সমাধান হতে পারে? docs.microsoft.com/en-us/dotnet/csharp/nullable-references রিটার্নিং nullকিনা নির্বিশেষে Tহয় Objectবা intবা char
আলেকজান্ডার - মনিকা পুনরায় ইনস্টল করুন

উত্তর:


968

দুটি বিকল্প:

  • রিটার্ন default(T)আপনি ফিরে আসবেন যার মানে nullযদি টি একটি রেফারেন্স টাইপ (বা একটি nullable মান প্রকার) হয়, 0জন্য int, '\0'জন্য char, ইত্যাদি ( ডিফল্ট মান টেবিল (গ # রেফারেন্স) )
  • টি কে সীমাবদ্ধতার সাথে একটি রেফারেন্স টাইপ হিসাবে where T : classসীমাবদ্ধ করুন এবং তারপরে nullস্বাভাবিক হিসাবে ফিরুন

3
আমার রিটার্ন টাইপ যদি এনাম হয় তবে ক্লাস নয়? আমি টি নির্দিষ্ট করতে পারি না: এনাম :(
জাস্টিন

1
.NET এ এনাম একটি পূর্ণসংখ্যার প্রকারের চারপাশে খুব পাতলা (এবং ফাঁসযুক্ত) মোড়ক হয়। কনভেনশনটি হ'ল আপনার "ডিফল্ট" এনাম মানের জন্য শূন্য ব্যবহার করা।
মাইক চেম্বারলাইন

27
আমি মনে করি এর সাথে সমস্যাটি হ'ল যদি আপনি এই জেনেরিক পদ্ধতিটি বলার জন্য ব্যবহার করেন তবে একটি ডেটাবেস অবজেক্টকে DbNull থেকে INT তে রূপান্তর করুন এবং এটি ডিফল্ট (টি) যেখানে T এর কোন int হবে, ফিরে আসবে 0. যদি এই সংখ্যাটি হয় আসলে অর্থবহ, তারপর ক্ষেত্রটি শূন্য ছিল এমন ক্ষেত্রে আপনি খারাপ ডেটা ঘুরে দেখছেন। অথবা এর চেয়ে আরও ভাল উদাহরণ হ'ল ডেটটাইম। ক্ষেত্রটি যদি "ডেটক্লোজড" এর মতো কিছু ছিল এবং এটি শূন্য হিসাবে ফিরিয়ে দেওয়া হয়েছে কারণ এবং অ্যাকাউন্টটি এখনও খোলা আছে, এটি প্রকৃতপক্ষে ডিফল্ট হবে (ডেটটাইম) 1/1/0000 এ, কম্পিউটারটি আবিষ্কার হওয়ার আগে অ্যাকাউন্টটি বন্ধ হয়ে যাওয়ার ইঙ্গিত দেয়।
সিনায়েস্টিক

21
@ সিনেস্টেথিক: সুতরাং আপনি তার পরিবর্তে Nullable<int>বা Nullable<DateTime>পরিবর্তিত হবেন । যদি আপনি একটি অ-শনীয় প্রকারের ব্যবহার করেন এবং কোনও নাল মান উপস্থাপন করতে চান তবে আপনি কেবল সমস্যার জন্য বলছেন।
জন স্কিটি

1
আমি একমত, আমি কেবল এটি সামনে আনতে চেয়েছিলাম আমি মনে করি আমি যা করছি তা আরও মাইমাথোদ <টি> () এর মতো; এটি ধরে নেওয়া যে এটি একটি নন-অযোগ্য প্রকার এবং মাইমেথোদ <টি?> (); ধরে নেওয়া এটি একটি ক্ষয়যোগ্য প্রকার। সুতরাং আমার পরিস্থিতিতে, আমি একটি নাল ধরতে এবং সেখান থেকে যেতে একটি অস্থায়ী ভেরিয়েবল ব্যবহার করতে পারি।
সিনাস্টেস্টিক

84
return default(T);


1
হতাশ, আমি এই কীওয়ার্ডটি সম্পর্কে জানতে পারলে অনেক সময় বাঁচাতে পারতাম - ধন্যবাদ রিকার্ডো!
আনা বেটস

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

33

আপনি কেবল নিজের সীমাবদ্ধতাগুলি সামঞ্জস্য করতে পারেন:

where T : class

তারপরে নাল ফেরার অনুমতি রয়েছে।


ধন্যবাদ। আমি গ্রহণযোগ্য সমাধান হিসাবে 2 টি উত্তর চয়ন করতে পারি না, তাই আমি জন স্কিটির কারণ হিসাবে তার উত্তরটির দুটি সমাধান রয়েছে choose
এডোসফট

@ মিগল এটি আপনার প্রয়োজনীয়তার উপর নির্ভর করে। হতে পারে তাদের প্রকল্পের এটির প্রয়োজন নেই IDisposable। হ্যাঁ, বেশিরভাগ সময় এটি হতে হয় না। উদাহরণস্বরূপ System.Stringবাস্তবায়ন করে না IDisposable। উত্তরদাতাকে এটি পরিষ্কার করে দেওয়া উচিত ছিল, তবে এটি উত্তর ভুল করে না। :)
অহ্ম্ম

@ মিগোলের আমার সেখানে কোনও পরিচয় নেই বলে আমার কোনও ধারণা নেই। সরানো হয়েছে।
TheSoftwareJedi

13

আপনার জেনেরিক ধরণের প্রথম সীমাবদ্ধতা হিসাবে শ্রেণি সীমাবদ্ধতা যুক্ত করুন।

static T FindThing<T>(IList collection, int id) where T : class, IThing, new()

ধন্যবাদ। আমি গ্রহণযোগ্য সমাধান হিসাবে 2 টি উত্তর চয়ন করতে পারি না, তাই আমি জন স্কিটির কারণ চয়ন করি তার উত্তরটির দুটি সমাধান রয়েছে।
এডোসফট

7
  1. আপনার যদি আপত্তি থাকে তবে টাইপকাস্ট করতে হবে

    return (T)(object)(employee);
  2. আপনার যদি শূন্য ফিরে আসতে হয়

    return default(T);

হাই ইউজার 725388, দয়া করে প্রথম বিকল্পটি যাচাই করুন
জোসেফ জর্জ

7

নীচে আপনি দুটি বিকল্প ব্যবহার করতে পারেন

return default(T);

অথবা

where T : class, IThing
 return null;

6

আপনার অন্যান্য বিকল্পটি হ'ল এটি আপনার ঘোষণার শেষে যুক্ত করা:

    where T : class
    where T: IList

এইভাবে এটি আপনাকে শূন্য ফিরে আসতে দেবে।


উভয় সীমাবদ্ধতা একই ধরণের হয়, আপনি একবার টাইপ উল্লেখ এবং মত একটি কমা ব্যবহার করুন where T : class, IList। আপনার যদি বিভিন্ন ধরণের সীমাবদ্ধতা থাকে তবে আপনি টোকেনটি পুনরায় whereহিসাবে পুনরায় দিন where TFoo : class where TBar : IList
জেপ্প স্টিগ নীলসেন

3

থসফটওয়ারজেদি কাজগুলির সমাধান,

এছাড়াও আপনি কয়েকটি মান এবং অবনমিত প্রকারের সাহায্যে এটি সংরক্ষণাগারভুক্ত করতে পারেন:

static T? FindThing<T>(IList collection, int id) where T : struct, IThing
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;
}

1

ত্রুটির সুপারিশ নিন ... এবং হয় ব্যবহারকারী default(T)বা new T

আপনি যদি সেই রাস্তাটিতে যান তবে এটি একটি বৈধ মিল ছিল কিনা তা নিশ্চিত করতে আপনাকে আপনার কোডের সাথে একটি তুলনা যুক্ত করতে হবে।

অন্যথায়, "মিল পাওয়া গেছে" এর জন্য একটি আউটপুট প্যারামিটার সম্ভাব্য বিবেচনা করুন।


1

নুলাবল এনুম রিটার্ন মানগুলির জন্য এখানে একটি কার্যকারী উদাহরণ:

public static TEnum? ParseOptional<TEnum>(this string value) where TEnum : struct
{
    return value == null ? (TEnum?)null : (TEnum) Enum.Parse(typeof(TEnum), value);
}

সি # 7.3 (মে 2018) থেকে আপনি সীমাবদ্ধতা উন্নতি করতে পারেন where TEnum : struct, Enum। এটি নিশ্চিত করে যে একজন কলকারী দুর্ঘটনাক্রমে কোনও মান ধরণের সরবরাহ করে না যা এনাম নয় (যেমন একটি intবা একটি DateTime)।
জেপ্পে স্টিগ নীলসেন

0

উপরে উপস্থাপন করা 2 টি উত্তরের আর একটি বিকল্প। আপনি যদি আপনার রিটার্নের ধরনটি এতে পরিবর্তন করেন তবে আপনি ফিরে আসতে objectপারবেন null, একই সময়ে নন-নাল রিটার্নটি কাস্ট করুন।

static object FindThing<T>(IList collection, int id)
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return (T) thing;
    }
    return null;  // allowed now
}

অবক্ষয়: এটির জন্য ফিরে আসা অবজেক্ট (নন-নাল ক্ষেত্রে) কাস্ট করার জন্য পদ্ধতির কলারের প্রয়োজন হবে, যা বক্সিং -> কম পারফরম্যান্সকে বোঝায়। আমি কি সঠিক?
চিশার্পেস্ট

0

সম্পূর্ণতার জন্য, আপনি এটি করতে পারেন তা জেনে রাখা ভাল:

return default;

এটি হিসাবে একই ফেরত return default(T);


0

আমার জন্য এটি যেমন হয় তেমন কাজ করে। সমস্যা ঠিক কোথায়?

public static T FindThing<T>(this IList collection, int id) where T : IThing, new()
{
    foreach (T thing in collection)
    {
        if (thing.Id == id)
            return thing;
        }
    }

    return null; //work
    return (T)null; //work
    return null as T; //work
    return default(T); //work


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