নাল মানগুলি পরীক্ষা করার সঠিক উপায় কী?


122

আমি নাল-কোলেসিং অপারেটরটিকে পছন্দ করি কারণ এটি নলযোগ্য প্রকারের জন্য একটি ডিফল্ট মান নির্ধারণ করা সহজ করে।

 int y = x ?? -1;

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

আমি আশা করি আমি এটি করতে পারতাম:

string y = Session["key"].ToString() ?? "none";

তবে আপনি পারবেন না কারণ .ToString()নাল চেকের আগে ডেকে আনা হয়েছে তাই নাল হলে এটি ব্যর্থ Session["key"]হয়। আমি এই কাজ শেষ করছি:

string y = Session["key"] == null ? "none" : Session["key"].ToString();

এটি তিন লাইনের বিকল্পের চেয়ে আমার মতে এটি কাজ করে এবং ভাল:

string y = "none";
if (Session["key"] != null)
    y = Session["key"].ToString();

যদিও এটি কাজ করে আমি আরও কৌতূহল বোধ করি যদি আরও ভাল উপায় থাকে তবে। আমার কাছে সবসময় Session["key"]দুবার রেফারেন্স দেওয়ার বিষয়টি বিবেচনা করে না; একবার চেকের জন্য, এবং আবার অ্যাসাইনমেন্টের জন্য। কোন ধারনা?


20
গ্রুভির.? মতো সি # এর একটি "নিরাপদ নেভিগেশন অপারেটর" ( ) থাকুক এমনটাই আমি চাই ।
ক্যামেরন

2
@ ক্যামেরন: এটি যখন আমি ইচ্ছা করি সি # মোনাদ হিসাবে অকার্যকর প্রকারগুলি (রেফারেন্স প্রকারগুলি সহ) আচরণ করতে পারে, সুতরাং আপনার কোনও "নিরাপদ নেভিগেশন অপারেটর" লাগবে না।
জন পুর্ডি

3
নাল রেফারেন্সের উদ্ভাবক এটিকে তার "বিলিয়ন ডলারের ভুল" হিসাবে অভিহিত করেছেন এবং আমি তাতে সম্মত হতে চাই। Infoq.com/preferencesations/…
জেমি

তার আসল ভুলটি হ'ল অনিরাপদ (ভাষা প্রয়োগ নয়) নালযোগ্য এবং নন-নুলাবলিক প্রকারের মিশ্রণ।
MSalters 22'12

@ জামিআইডি একটি খুব আকর্ষণীয় লিঙ্কের জন্য ধন্যবাদ। :)
ববরোডস

উত্তর:


182

কি সম্পর্কে

string y = (Session["key"] ?? "none").ToString();

79
এই এক সঙ্গে শক্তি শক্তিশালী।
শেভ


1
@ ব্ল্যাকবায়ার তবে প্রত্যাবর্তিত মানটি সম্ভবত একটি স্ট্রিং, তাই valid
ালাই

এটি আমার প্রশ্নের সর্বাধিক প্রত্যক্ষ উত্তর ছিল তাই আমি উত্তরটি চিহ্নিত করছি, তবে জন স্কিটির এক্সটেনশন পদ্ধতিটি .ToStringOrDefault()এটি করা আমার পছন্দসই পদ্ধতি । যাইহোক, আমি জনের এক্সটেনশন পদ্ধতির মধ্যে এই উত্তরটি ব্যবহার করছি;)
শেভ

10
আমি এটি অপছন্দ করি কারণ আপনার প্রোগ্রামটিতে কিছু সূক্ষ্ম বাগ লুকিয়ে থাকতে পারে বলে আপনি যদি আশা করেন তার চেয়ে আপনার অধিবেশনে অন্য কোনও ধরণের অবজেক্ট থাকে। আমি বরং একটি নিরাপদ castালাই ব্যবহার করব কারণ আমি মনে করি এটির ত্রুটিগুলি আরও দ্রুত ছড়িয়ে দেওয়ার সম্ভাবনা রয়েছে। এটি স্ট্রিং অবজেক্টে টসস্ট্রিং () কল করাও এড়িয়ে যায়।
tvanfosson

130

আপনি যদি প্রায়শই এটির সাথে বিশেষত করে থাকেনToString() তবে আপনি একটি এক্সটেনশন পদ্ধতি লিখতে পারেন:

public static string NullPreservingToString(this object input)
{
    return input == null ? null : input.ToString();
}

...

string y = Session["key"].NullPreservingToString() ?? "none";

অথবা একটি পদ্ধতি অবশ্যই একটি ডিফল্ট গ্রহণ করে:

public static string ToStringOrDefault(this object input, string defaultValue)
{
    return input == null ? defaultValue : input.ToString();
}

...

string y = Session["key"].ToStringOrDefault("none");

16
.ToStringOrDefault()সহজ এবং elegant। একটি দুর্দান্ত সমাধান।
শেভ

7
আমি এর সাথে মোটেও একমত হতে পারি না। এতে সম্প্রসারণের পদ্ধতিগুলি objectএকটি অভিশাপ এবং একটি কোড বেসকে জঞ্জাল করে এবং নথ thisমানগুলিতে ত্রুটি ছাড়াই পরিচালিত এক্সটেনশন পদ্ধতিগুলি খাঁটি মন্দ।
নিক লারসেন

10
@ নিকলারসেন: সবকিছুই সংযত in নাল দিয়ে কাজ করে এমন এক্সটেনশন পদ্ধতিগুলি খুব কার্যকর হতে পারে, আইএমও - যতক্ষণ না তারা কী করে সে সম্পর্কে তারা পরিষ্কার
জন স্কিটি

3
@ one.beat.consumer: হ্যাঁ। যদি এটি স্রেফ বিন্যাস (বা কোনও টাইপস) থাকত তবে এটি একটি জিনিস হত তবে কোনও লেখকের পদ্ধতির নাম পরিবর্তন করা আইএমওর যথাযথ সম্পাদনের বাইরে is
জন স্কিটি

6
@ one.beat.consumer: ব্যাকরণ এবং টাইপগুলি সংশোধন করার সময়, এটি ঠিক আছে - তবে এমন একটি নাম পরিবর্তন করা যা কেউ (কেবলমাত্র আমি নয়) স্পষ্টভাবে আমার বেছে নেওয়া হয়েছে তা আমার কাছে আলাদা মনে হয়। এই মুহুর্তে, আমি পরিবর্তে একটি মন্তব্যে এটি পরামর্শ করব।
জন স্কিটি

21

আপনি ব্যবহার করতে পারেন as, যা nullরূপান্তর ব্যর্থ হলে ফলন দেয়:

Session["key"] as string ?? "none"

এই ফিরে আসবে "none" এমনকি যদি কেউ কোনো স্টাফ intমধ্যে Session["key"]


1
এটি কেবল তখনই কাজ করে যখন আপনার ToString()প্রথম স্থানে প্রয়োজন হবে না ।
আবেল

1
আমি অবাক হয়েছি কেউ এই উত্তরটি এখনও কমিয়ে দেয়নি। ওপি যা করতে চায় তা থেকে এটি শব্দার্থগতভাবে সম্পূর্ণ আলাদা।
টিমউই

@ টিমউই: ওপি ToString()স্ট্রিং যুক্ত কোনও বস্তুকে স্ট্রিনে রূপান্তর করতে ব্যবহার করে। আপনি obj as stringবা সঙ্গে একই কাজ করতে পারেন (string)obj। এটিএসপি.এনইটি-তে মোটামুটি সাধারণ পরিস্থিতি।
Andomar

5
@ অ্যান্ডোমার: না, ওপি এমন ToString()কোনও বস্তুর (যথা Session["key"]) কল দিচ্ছে যার ধরন তিনি উল্লেখ করেননি। এটি কোনও ধরণের অবজেক্ট হতে পারে, স্ট্রিং নয়।
টিমউই

13

এটি সর্বদা একটি হয়ে থাকলে stringআপনি কাস্ট করতে পারেন:

string y = (string)Session["key"] ?? "none";

কেউ যদি কোনও intকিছু বা কিছু দিয়ে থাকে তবে ভুলটি লুকানোর পরিবর্তে অভিযোগ করার সুবিধা রয়েছে Session["key"]। ;)


10

প্রস্তাবিত সমাধানগুলির সবগুলিই ভাল, এবং প্রশ্নের উত্তর দিন; সুতরাং এটি কেবল এটি সামান্য প্রসারিত করা হয়। বর্তমানে বেশিরভাগ উত্তর কেবল নাল বৈধতা এবং স্ট্রিংয়ের ধরণের সাথে ডিল করে। আপনি StateBagজেনেরিক অন্তর্ভুক্ত করতে অবজেক্টটি প্রসারিত করতে পারেনGetValueOrDefault জেন স্কিকেট পোস্ট করা উত্তরের অনুরূপ পদ্ধতি ।

একটি সাধারণ জেনেরিক এক্সটেনশন পদ্ধতি যা কোনও স্ট্রিংটিকে কী হিসাবে স্বীকার করে এবং তারপরে টাইপ করে সেশন অবজেক্টটি পরীক্ষা করে। যদি বস্তুটি নাল হয় বা একই ধরণের না হয় তবে ডিফল্টটি ফিরে আসে, অন্যথায় সেশন মানটি দৃ strongly়ভাবে টাইপ করা হয়।

এটার মতো কিছু

/// <summary>
/// Gets a value from the current session, if the type is correct and present
/// </summary>
/// <param name="key">The session key</param>
/// <param name="defaultValue">The default value</param>
/// <returns>Returns a strongly typed session object, or default value</returns>
public static T GetValueOrDefault<T>(this HttpSessionState source, string key, T defaultValue)
{
    // check if the session object exists, and is of the correct type
    object value = source[key]
    if (value == null || !(value is T))
    {
        return defaultValue;
    }

    // return the session object
    return (T)value;
}

1
আপনি কি এই এক্সটেনশন পদ্ধতির জন্য কোনও ব্যবহারের নমুনা অন্তর্ভুক্ত করতে পারেন? স্টেটব্যাগটি কি রাষ্ট্রের সাথে দেখা এবং সেশনের সাথে চুক্তি করে না? আমি এএসপি.নেট এমভিসি 3 ব্যবহার করছি যাতে আমার সত্যিই রাষ্ট্র দেখার সহজ সরল অ্যাক্সেস না পায়। আমি মনে করি আপনি প্রসারিত করতে চান HttpSessionState
শেভ

এই উত্তরটির জন্য সফল হয় যদি মান 3x এবং 2 টি ক্যাসেট পুনরুদ্ধার করা প্রয়োজন। (আমি জানি এটি একটি অভিধান, তবে নতুনরা ব্যয়বহুল পদ্ধতিতে অনুরূপ অনুশীলনগুলি ব্যবহার করতে পারে))
জ্যাক বার্গার

3
T value = source[key] as T; return value ?? defaultValue;
জেক বার্গার

1
@ জ্যাবার্গার "হিসাবে" ব্যবহার করে কাস্টিং অবধি অ্যাক্সেসযোগ্য কারণ জেনেরিক ধরণের কোনও শ্রেণির বাধা নেই যতটা সম্ভবত আপনি বুলের মতো কোনও মান ফিরিয়ে দিতে চাইতে পারেন। @ অ্যালেক্সফোর্ড আমার ক্ষমা প্রার্থনা, আপনি HttpSessionStateসেশনটির জন্য প্রসারিত করতে চাইবেন । :)
রিচার্ড

প্রকৃতপক্ষে. রিচার্ড হিসাবে উল্লেখ করা হয়েছে, সীমাবদ্ধতা প্রয়োজন। (... এবং যদি আপনি মানের ধরণের ব্যবহার করতে চান তবে অন্য একটি পদ্ধতি)
জেক বার্গার

7

আমরা একটি পদ্ধতি ব্যবহার করি NullOr

ব্যবহার

// Call ToString() if it’s not null, otherwise return null
var str = myObj.NullOr(obj => obj.ToString());

// Supply default value for when it’s null
var str = myObj.NullOr(obj => obj.ToString()) ?? "none";

// Works with nullable return values, too —
// this is properly typed as “int?” (nullable int)
// even if “Count” is just int
var count = myCollection.NullOr(coll => coll.Count);

// Works with nullable input types, too
int? unsure = 47;
var sure = unsure.NullOr(i => i.ToString());

উৎস

/// <summary>Provides a function delegate that accepts only value types as return types.</summary>
/// <remarks>This type was introduced to make <see cref="ObjectExtensions.NullOr{TInput,TResult}(TInput,FuncStruct{TInput,TResult})"/>
/// work without clashing with <see cref="ObjectExtensions.NullOr{TInput,TResult}(TInput,FuncClass{TInput,TResult})"/>.</remarks>
public delegate TResult FuncStruct<in TInput, TResult>(TInput input) where TResult : struct;

/// <summary>Provides a function delegate that accepts only reference types as return types.</summary>
/// <remarks>This type was introduced to make <see cref="ObjectExtensions.NullOr{TInput,TResult}(TInput,FuncClass{TInput,TResult})"/>
/// work without clashing with <see cref="ObjectExtensions.NullOr{TInput,TResult}(TInput,FuncStruct{TInput,TResult})"/>.</remarks>
public delegate TResult FuncClass<in TInput, TResult>(TInput input) where TResult : class;

/// <summary>Provides extension methods that apply to all types.</summary>
public static class ObjectExtensions
{
    /// <summary>Returns null if the input is null, otherwise the result of the specified lambda when applied to the input.</summary>
    /// <typeparam name="TInput">Type of the input value.</typeparam>
    /// <typeparam name="TResult">Type of the result from the lambda.</typeparam>
    /// <param name="input">Input value to check for null.</param>
    /// <param name="lambda">Function to apply the input value to if it is not null.</param>
    public static TResult NullOr<TInput, TResult>(this TInput input, FuncClass<TInput, TResult> lambda) where TResult : class
    {
        return input == null ? null : lambda(input);
    }

    /// <summary>Returns null if the input is null, otherwise the result of the specified lambda when applied to the input.</summary>
    /// <typeparam name="TInput">Type of the input value.</typeparam>
    /// <typeparam name="TResult">Type of the result from the lambda.</typeparam>
    /// <param name="input">Input value to check for null.</param>
    /// <param name="lambda">Function to apply the input value to if it is not null.</param>
    public static TResult? NullOr<TInput, TResult>(this TInput input, Func<TInput, TResult?> lambda) where TResult : struct
    {
        return input == null ? null : lambda(input);
    }

    /// <summary>Returns null if the input is null, otherwise the result of the specified lambda when applied to the input.</summary>
    /// <typeparam name="TInput">Type of the input value.</typeparam>
    /// <typeparam name="TResult">Type of the result from the lambda.</typeparam>
    /// <param name="input">Input value to check for null.</param>
    /// <param name="lambda">Function to apply the input value to if it is not null.</param>
    public static TResult? NullOr<TInput, TResult>(this TInput input, FuncStruct<TInput, TResult> lambda) where TResult : struct
    {
        return input == null ? null : lambda(input).Nullable();
    }
}

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

... এবং 'নামকরণ' হ'ল এটির সাথে আসল সমস্যাটি - কিছুই সত্যই সঠিকভাবে চিত্রিত হয় না বলে মনে হয় (বা 'বেশি' যোগ করে) বা দীর্ঘ হয় - নুলআর ভাল তবে 'নাল' আইএমও-তে খুব বেশি জোর দেওয়া হয় (আরও আপনি have ?? still) - 'সম্পত্তি', বা 'নিরাপদ' হ'ল আমি ব্যবহার করেছি। মান.ডট (o => o.property) ?? @ ডিফল্ট সম্ভবত?
এনএসগাগা-বেশিরভাগ-নিষ্ক্রিয়

@ এনএসগাগা: আমরা বেশ কিছু সময়ের জন্য নামটির পিছনে পিছনে পিছনে গিয়েছিলাম। আমরা বিবেচনা করেছিলাম Dotকিন্তু এটি খুব বর্ণনামূলক খুঁজে পেয়েছি। আমরা NullOrস্ব-ব্যাখ্যা এবং সংকোচনের মধ্যে একটি ভাল বাণিজ্য হিসাবে সেটেল করেছি। আপনি যদি নামটির বিষয়ে আদৌ যত্ন না করেন তবে আপনি সর্বদা এটি কল করতে পারেন _। আপনি যদি ল্যাম্বডাসকে লিখতে খুব জটিল মনে করেন তবে আপনি এটির জন্য একটি স্নিপেট ব্যবহার করতে পারেন, তবে ব্যক্তিগতভাবে আমি এটি যথেষ্ট সহজ বলে মনে করি। হিসাবে ? :, আপনি আরও জটিল অভিব্যক্তি সহ এটি ব্যবহার করতে পারবেন না, আপনাকে এগুলি একটি নতুন স্থানীয় স্থানান্তর করতে হবে; NullOrআপনাকে এড়াতে দেয়
টিমউই

6

আমার পছন্দটি, এক বারের জন্য, কী দিয়ে সঞ্চিত বস্তুটি যদি না থাকে সে ক্ষেত্রে স্ট্রিংয়ের জন্য নিরাপদ কাস্ট ব্যবহার করা হবে। ব্যবহারের ToString()ফলে আপনি চান ফলাফল নাও থাকতে পারে।

var y = Session["key"] as string ?? "none";

@ জোন স্কিটি যেমন বলেছে, আপনি যদি নিজেকে এটি অনেক বেশি করে একটি এক্সটেনশন পদ্ধতি বা আরও ভাল করে দেখেন তবে তবুও সম্ভবত একটি দৃ extension়ভাবে টাইপ করা সেশন র‌্যাপার শ্রেণীর সাথে একত্রে একটি এক্সটেনশন পদ্ধতি। এমনকি এক্সটেনশন পদ্ধতি ছাড়াই, দৃ strongly়ভাবে টাইপ করা র‍্যাপারটি ভাল ধারণা হতে পারে।

public class SessionWrapper
{
    private HttpSessionBase Session { get; set; }

    public SessionWrapper( HttpSessionBase session )
    {
        Session = session;
    }

    public SessionWrapper() : this( HttpContext.Current.Session ) { }

    public string Key
    {
         get { return Session["key"] as string ?? "none";
    }

    public int MaxAllowed
    {
         get { return Session["maxAllowed"] as int? ?? 10 }
    }
}

হিসাবে ব্যবহার

 var session = new SessionWrapper(Session);

 string key = session.Key;
 int maxAllowed = session.maxAllowed;

3

একটি সহায়ক ফাংশন তৈরি করুন

public static String GetValue( string key, string default )
{
    if ( Session[ key ] == null ) { return default; }
    return Session[ key ].toString();
}


string y = GetValue( 'key', 'none' );

2

স্কিটির উত্তরটি সর্বোত্তম - বিশেষত আমার কাছে মনে হয় তিনি ToStringOrNull()বেশ মার্জিত এবং আপনার প্রয়োজনের সাথে স্যুট। আমি এক্সটেনশন পদ্ধতির তালিকায় আরও একটি বিকল্প যুক্ত করতে চেয়েছিলাম:

জন্য মূল বস্তু বা ডিফল্ট স্ট্রিং মান ফিরুন নাল :

// Method:
public static object OrNullAsString(this object input, string defaultValue)
{
    if (defaultValue == null)
        throw new ArgumentNullException("defaultValue");
    return input == null ? defaultValue : input;
}

// Example:
var y = Session["key"].OrNullAsString("defaultValue");

varপ্রত্যাশিত মানটির জন্য ব্যবহার করুন কারণ এটি আসল ইনপুট টাইপ হিসাবে ফিরে আসবে, কেবল যখন ডিফল্ট স্ট্রিং হিসাবেnull


null defaultValueএটির প্রয়োজন না হলে কেন একটি ব্যতিক্রম নিক্ষেপ করবেন (এটি input != null)?
আটটিলা

একটি input != nullইওল নিজের মতো করে বস্তুটিকে ফিরিয়ে দেবে। input == nullপ্যারাম হিসাবে সরবরাহ করা একটি স্ট্রিং প্রদান করে। সুতরাং কোনও ব্যক্তি কল করতে পারে .OnNullAsString(null)- তবে উদ্দেশ্যটি (খুব কমই কার্যকর এক্সটেনশন পদ্ধতি হলেও) হ'ল এটি নিশ্চিত করা ছিল যে আপনি
কোনওভাবেই

input!=nullদৃশ্যকল্প শুধুমাত্র ইনপুট ফিরে আসবে যদি defaultValue!=nullআরো ঝুলিতে; অন্যথায় এটি একটি নিক্ষেপ করবে ArgumentNullException
আটটিলা

0

.NET যে সমর্থন করে না? এর সংস্করণগুলির জন্য এটি আমার সামান্য প্রকারের নিরাপদ "এলভিস অপারেটর"।

public class IsNull
{
    public static O Substitute<I,O>(I obj, Func<I,O> fn, O nullValue=default(O))
    {
        if (obj == null)
            return nullValue;
        else
            return fn(obj);
    }
}

প্রথম যুক্তি হ'ল পরীক্ষিত বস্তু। দ্বিতীয়টি হচ্ছে ফাংশন। এবং তৃতীয়টি নাল মান। সুতরাং আপনার ক্ষেত্রে:

IsNull.Substitute(Session["key"],s=>s.ToString(),"none");

এটি নালাগুলি ধরণের জন্যও খুব দরকারী। উদাহরণ স্বরূপ:

decimal? v;
...
IsNull.Substitute(v,v.Value,0);
....
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.