C # या .NET में सबसे खराब गोचा क्या है? [बन्द है]


377

मैं हाल ही में एक DateTimeवस्तु के साथ काम कर रहा था , और कुछ इस तरह लिखा था:

DateTime dt = DateTime.Now;
dt.AddDays(1);
return dt; // still today's date! WTF?

यह AddDays()कहने के लिए कि यह एक दिन है, जो यह नहीं कहता है - यह वास्तव में एक दिन के साथ एक तारीख देता है, इसलिए आपको इसे लिखना होगा:

DateTime dt = DateTime.Now;
dt = dt.AddDays(1);
return dt; // tomorrow's date

यह एक बार पहले मुझे कई बार काट चुका है, इसलिए मैंने सोचा कि यह सबसे खराब C # गोचा को सूचीबद्ध करने के लिए उपयोगी होगा।


157
वापसी DateTime.Now.AddDays (1);
क्रैशमास

23
AFAIK, मूल्य प्रकारों में निर्मित सभी अपरिवर्तनीय हैं, कम से कम उस प्रकार में शामिल किसी भी विधि में मौजूदा आइटम को संशोधित करने के बजाय एक नया आइटम देता है। कम से कम, मैं अपने सिर के ऊपर से एक के बारे में नहीं सोच सकता जो ऐसा नहीं करता है: सभी अच्छे और सुसंगत।
जोएल कोएहॉर्न

6
म्यूटेबल वैल्यू टाइप: System.Collections.Generics.List.Enumerator :( (और हां, यदि आप पर्याप्त प्रयास करते हैं तो आप इसे अजीब तरह से व्यवहार करते हुए देख सकते हैं।)
जॉन स्कीट

13
इंटेलीजेंस आपको वह सभी जानकारी देता है, जिसकी आपको आवश्यकता है। यह कहता है कि यह एक DateTime ऑब्जेक्ट देता है। यदि यह सिर्फ आपके द्वारा पास किए गए को बदल देता है, तो यह एक शून्य विधि होगी।
जॉन क्राफ्ट

20
जरूरी नहीं: StringBuilder.Append (...) उदाहरण के लिए "यह" देता है। यह धाराप्रवाह इंटरफेस में काफी आम है।
जॉन स्कीट

जवाबों:


304
private int myVar;
public int MyVar
{
    get { return MyVar; }
}

Blammo। आपका ऐप बिना स्टैक ट्रेस के क्रैश हो जाता है। हमेशा होता है।

( MyVarगेटटर myVarमें लोअरकेस के बजाय नोटिस कैपिटल ।)


112
और इस साइट के लिए उपयुक्त है :)
gbjbaanb

62
मैंने निजी सदस्य पर अंडरस्कोर लगाया, बहुत मदद करता है!
चक्रित

61
मैं स्वत: गुणों का उपयोग करता हूं, जहां मैं कर सकता हूं, इस तरह की समस्या को रोकता है;)
TWith2Sugars

28
यह आपकी निजी क्षेत्रों के लिए उपसर्गों उपयोग करने के लिए एक महान कारण है (वहाँ दूसरों रहे हैं, लेकिन यह एक अच्छा एक है): _myVar, m_myVar
jrista

205
@ जिक्र: ओ प्लीज नो ... नॉट एम_ ... अरघ द हॉरर ...
fretje

254

Type.GetType

जो मैंने देखा है वह बहुत से लोगों को काटता है Type.GetType(string)। वे आश्चर्य करते हैं कि यह अपनी विधानसभा में प्रकारों के लिए क्यों काम करता है, और कुछ प्रकार पसंद करते हैं System.String, लेकिन नहीं System.Windows.Forms.Form। इसका उत्तर यह है कि यह केवल वर्तमान विधानसभा और में दिखता है mscorlib


अनाम तरीके

C # 2.0 ने गुमनाम तरीके पेश किए, जिससे इस तरह की स्थिति खराब हो गई:

using System;
using System.Threading;

class Test
{
    static void Main()
    {
        for (int i=0; i < 10; i++)
        {
            ThreadStart ts = delegate { Console.WriteLine(i); };
            new Thread(ts).Start();
        }
    }
}

वह क्या छपेगा? खैर, यह पूरी तरह से शेड्यूलिंग पर निर्भर करता है। यह 10 नंबर प्रिंट करेगा, लेकिन यह संभवतः 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 प्रिंट नहीं करेगा, जो कि आप उम्मीद कर सकते हैं। समस्या यह है कि यह वह iचर है जिस पर कब्जा कर लिया गया है, प्रतिनिधि के निर्माण के बिंदु पर इसका मूल्य नहीं है। इसे सही दायरे के एक अतिरिक्त स्थानीय चर के साथ आसानी से हल किया जा सकता है:

using System;
using System.Threading;

class Test
{
    static void Main()
    {
        for (int i=0; i < 10; i++)
        {
            int copy = i;
            ThreadStart ts = delegate { Console.WriteLine(copy); };
            new Thread(ts).Start();
        }
    }
}

इटरेटर ब्लॉकों के आस्थगित निष्पादन

यह "गरीब आदमी की इकाई परीक्षण" पास नहीं है - क्यों नहीं?

using System;
using System.Collections.Generic;
using System.Diagnostics;

class Test
{
    static IEnumerable<char> CapitalLetters(string input)
    {
        if (input == null)
        {
            throw new ArgumentNullException(input);
        }
        foreach (char c in input)
        {
            yield return char.ToUpper(c);
        }
    }

    static void Main()
    {
        // Test that null input is handled correctly
        try
        {
            CapitalLetters(null);
            Console.WriteLine("An exception should have been thrown!");
        }
        catch (ArgumentNullException)
        {
            // Expected
        }
    }
}

इसका उत्तर यह है कि कोड के स्रोत के भीतर CapitalLettersकोड इटमर के होने तक निष्पादित नहीं होता हैMoveNext() तरीका पहले नहीं कहा जाता है।

मुझे अपने ब्रेनटेसर्स पृष्ठ पर कुछ और विषमताएँ मिली हैं ।


25
इटरेटर उदाहरण कुटिल है!
जिमी

8
क्यों नहीं इसे 3 उत्तर में विभाजित किया जाए ताकि हम एक-दूसरे के बजाय एक-एक को वोट कर सकें?
चक्रित

13
@ अचक्रित: रेट्रोस्पेक्ट में, यह शायद एक अच्छा विचार रहा होगा, लेकिन मुझे लगता है कि अब बहुत देर हो चुकी है। यह भी लग सकता है कि मैं बस और अधिक प्रतिनिधि प्राप्त करने की कोशिश कर रहा था ...
जॉन स्कीट

19
वास्तव में Type.GetType काम करता है यदि आप असेंबली क्वॉलिफाइड नाम प्रदान करते हैं। Type.GetType ("System.ServiceModel.EndpointNotFoundException, System.ServiceModel, संस्करण = 3.0.0.0, संस्कृति = तटस्थ, PublicKeyToken = b77a5c56194e089");
चिल्टपम्प २ ch ’०

2
@kentaromiura: अधिभार संकल्प सबसे व्युत्पन्न प्रकार से शुरू होता है और पेड़ पर काम करता है - लेकिन केवल उन तरीकों को देख रहा है जो मूल रूप से घोषित प्रकार में देख रहे हैं। Foo (int) आधार विधि को ओवरराइड करता है, इसलिए ऐसा नहीं माना जाता है। फू (वस्तु) लागू है, इसलिए अधिभार संकल्प वहां रुक जाता है। अजीब है, मुझे पता है।
जॉन स्कीट

194

अपवादों को फिर से फेंकना

एक गेटचा जिसे बहुत सारे नए डेवलपर्स मिलते हैं, वह पुन: फेंक अपवाद शब्दार्थ है।

बहुत बार मुझे निम्नलिखित जैसे कोड दिखाई देते हैं

catch(Exception e) 
{
   // Do stuff 
   throw e; 
}

समस्या यह है कि यह स्टैक ट्रेस को मिटा देता है और मुद्दों को बहुत कठिन बना देता है, क्योंकि आप ट्रैक नहीं कर सकते हैं जहां अपवाद उत्पन्न हुआ।

सही कोड या तो कोई आर्गन के साथ फेंक स्टेटमेंट है:

catch(Exception)
{
    throw;
}

या अपवाद को एक और में लपेटकर, मूल स्टैक ट्रेस प्राप्त करने के लिए आंतरिक अपवाद का उपयोग करते हुए:

catch(Exception e) 
{
   // Do stuff 
   throw new MySpecialException(e); 
}

बहुत सौभाग्य से, मैंने अपने पहले सप्ताह में किसी के द्वारा इसके बारे में पढ़ाया और इसे अधिक वरिष्ठ डेवलपर्स के कोड में पाया। है: पकड़ () {फेंक; } दूसरा कोड स्निपेट के समान है? पकड़ (अपवाद ई) {फेंक; } केवल यह एक अपवाद वस्तु नहीं बनाता है और इसे आबाद करता है?
स्टुपरयूजर

थ्रो पूर्व (या फेंक ई) का उपयोग करने की त्रुटि के अलावा, बस फेंकने के लिए, मुझे आश्चर्य होगा कि क्या मामले हैं जब यह अपवाद को पकड़ने के लायक है केवल इसे फिर से फेंकने के लिए।
रयान लूनी

13
@Kyralessa: ऐसे कई मामले हैं: उदाहरण के लिए, यदि आप एक लेन-देन को रोलबैक करना चाहते हैं, तो इससे पहले कि कॉलर को अपवाद मिल जाए। आप रोलबैक करते हैं और फिर पुनर्विचार करते हैं।
आर। मार्टिनो फर्नांडिस

7
मैं यह सब समय देखता हूं, जहां लोग अपवादों को पकड़ते हैं और पुनर्विचार करते हैं, क्योंकि उन्हें सिखाया जाता है कि उन्हें सभी अपवादों को पकड़ना चाहिए, न कि यह महसूस करते हुए कि इसे कॉल स्टैक तक पकड़ा जाएगा। यह मुझे पागल कर देता है।
जेम्स वेस्टगेट

5
@Kyralessa सबसे बड़ा मामला है जब आपको लॉगिंग करनी है। कैच और रीथ्रो में त्रुटि लॉग करें ..
nawfal

194

हाइजेनबर्ग वॉच विंडो

यदि आप लोड-ऑन-डिमांड सामान कर रहे हैं, तो यह आपको बुरी तरह से काट सकता है:

private MyClass _myObj;
public MyClass MyObj {
  get {
    if (_myObj == null)
      _myObj = CreateMyObj(); // some other code to create my object
    return _myObj;
  }
}

अब मान लें कि आपके पास इसका उपयोग करने के लिए कहीं और कोड है:

// blah
// blah
MyObj.DoStuff(); // Line 3
// blah

अब आप अपने CreateMyObj()तरीके को डिबग करना चाहते हैं । तो आप कोड में कदम रखने के इरादे से ऊपर लाइन 3 पर एक ब्रेकपॉइंट लगाएं। बस अच्छे उपाय के लिए, आप उस रेखा के ऊपर _myObj = CreateMyObj();एक ब्रेकपॉइंट भी कहते हैं , और यहां तक ​​कि एक ब्रेकपॉइंट भी CreateMyObj()

कोड 3 पर आपके ब्रेकपॉइंट को हिट करता है। आप कोड में कदम रखते हैं। आप सशर्त कोड दर्ज करने की उम्मीद करते हैं, क्योंकि _myObjस्पष्ट रूप से अशक्त है, है ना? उह ... तो ... यह शर्त को क्यों छोड़ दिया और सीधे जाना चाहिए return _myObj? आप अपने माउस को _myObj पर घुमाएँ ... और वास्तव में, इसका कोई मूल्य नहीं है! ये कैसे हो गया?!

इसका उत्तर यह है कि आपके आईडीई ने इसका मूल्य प्राप्त किया है, क्योंकि आपके पास "घड़ी" खिड़की खुली है - विशेष रूप से "ऑटो" घड़ी खिड़की, जो निष्पादन की वर्तमान या पिछली पंक्ति के लिए प्रासंगिक सभी चर / गुणों के मूल्यों को प्रदर्शित करती है। जब आप लाइन 3 पर अपना ब्रेकपॉइंट मारते हैं, तो घड़ी की खिड़की ने फैसला किया कि आपको इसकी कीमत जानने में दिलचस्पी होगी MyObj- इसलिए पर्दे के पीछे, आपके किसी भी ब्रेकप्वाइंट को अनदेखा करते हुए , यह आपके लिए मूल्य की गणना करता है MyObj- जिसमें कॉल भी शामिल CreateMyObj()है _myObj का मान सेट करता है!

इसलिए मैं इसे हाइजेनबर्ग वॉच विंडो कहता हूं - आप इसे प्रभावित किए बिना मूल्य का निरीक्षण नहीं कर सकते ... :)

पकड़ लिया!


संपादित करें - मुझे लगता है कि @ ChristianHayter की टिप्पणी मुख्य उत्तर में शामिल किए जाने के योग्य है, क्योंकि यह इस मुद्दे के लिए एक प्रभावी समाधान जैसा दिखता है। तो कभी भी आपके पास एक आलसी-भरी संपत्ति है ...

[DebuggerBrowsable (DebuggerBrowsableState.Never)] या [DebuggerDisplay ("<मांग पर भरी हुई">) के साथ अपनी संपत्ति को सजाने। - क्रिश्चियन हेटर


10
शानदार खोज! आप एक प्रोग्रामर नहीं हैं, आप एक वास्तविक डिबगर हैं।
यह। __curious_geek

26
मैं इस पर भी चर में मंडरा रहा हूँ, न कि केवल घड़ी की खिड़की।
रिचर्ड मॉर्गन

31
के साथ अपनी संपत्ति को सजाने [DebuggerBrowsable(DebuggerBrowsableState.Never)]या [DebuggerDisplay("<loaded on demand>")]
ईसाई हैटर

4
यदि आप एक फ्रेमवर्क क्लास विकसित कर रहे हैं और एक आलसी-निर्मित संपत्ति के रनटाइम व्यवहार को बदलने के बिना विंडो कार्यक्षमता देखना चाहते हैं, तो आप डिबगर प्रकार प्रॉक्सी का उपयोग कर सकते हैं यदि यह पहले से निर्मित है, तो मान वापस करने के लिए प्रॉक्सी का उपयोग करें और यह संदेश दें कि संपत्ति नहीं है यदि ऐसा है तो निर्माण किया गया है। Lazy<T>वर्ग (इसके लिए विशेष रूप से Valueसंपत्ति) जहां इस प्रयोग किया जाता है की एक उदाहरण है।
सैम हैरवेल

4
मुझे याद है कि किसी व्यक्ति ने (किसी कारण से मैं थाह नहीं कर सकता) वस्तु के मूल्य को एक अधिभार में बदल दिया ToString। हर बार जब वह इसके ऊपर मंडराता था तो टूलटिप ने उसे एक अलग मूल्य दिया - वह इसका पता नहीं लगा सका ...
जेएनएफ

144

यहाँ एक और समय है जो मुझे मिलता है:

static void PrintHowLong(DateTime a, DateTime b)
{
    TimeSpan span = a - b;
    Console.WriteLine(span.Seconds);        // WRONG!
    Console.WriteLine(span.TotalSeconds);   // RIGHT!
}

TimeSpan.Seconds का समय (2 मिनट और 0 सेकंड सेकंड का 0 मान है) सेकंड का हिस्सा है।

TimeSpan.TotalSeconds सेकंड में मापे गए पूरे टाइमपेन है (2 मिनट का कुल सेकंड वैल्यू 120 है)।


1
हाँ, वह भी मुझे मिल गया है। मुझे लगता है कि यह TimeSpan.SecondsPart या कुछ और होना चाहिए ताकि यह स्पष्ट हो सके कि यह क्या दर्शाता है।
दान डिप्लो

3
इसे फिर से पढ़ने पर, मुझे आश्चर्य होता है कि TimeSpanयहां तक कि एक Secondsसंपत्ति भी क्यों है । एक चूहे के गधे को कौन देता है कि एक सेशन के सेकंड का हिस्सा क्या है, वैसे भी? यह एक मनमाना, इकाई-निर्भर मूल्य है; मैं इसके लिए किसी भी व्यावहारिक उपयोग की कल्पना नहीं कर सकता।
मुसिएनेसिस

2
मेरे लिए समझ में आता है कि TimeSpan.TotalSeconds वापस आ जाएगा ... समय अवधि में सेकंड की कुल संख्या।
एड एस।

16
@MusiGenesis संपत्ति उपयोगी है। क्या होगा यदि मैं टुकड़ों में टूटे हुए समय को प्रदर्शित करना चाहता हूं? उदाहरण के लिए, मान लें कि आपका Timespan hours 3 घंटे 15 मिनट 10 सेकंड ’की अवधि का प्रतिनिधित्व करता है। आप इस जानकारी को बिना सेकंड्स, आवर्स, मिनट्स की संपत्तियों के कैसे एक्सेस कर सकते हैं?
SolutionYogi

1
समान API में, मैंने उपयोग किया है SecondsPartऔर SecondsTotalदोनों को अलग करने के लिए।
ब्लूराजा - डैनी पफ्लुगुएफ्ट

80

मेमोरी को लीक करना क्योंकि आपने अन-हुक इवेंट नहीं किए।

यह भी मैं जानता हूँ कि कुछ वरिष्ठ डेवलपर्स को पकड़ा।

इसमें बहुत सी चीजों के साथ एक WPF फॉर्म की कल्पना करें, और कहीं न कहीं आप किसी घटना की सदस्यता लेते हैं। यदि आप अनसब्सक्राइब नहीं करते हैं तो पूरे फॉर्म को बंद और डी-रेफर किए जाने के बाद मेमोरी में इधर-उधर रखा जाता है।

मुझे विश्वास है कि मैंने जो मुद्दा देखा था, वह WPF फॉर्म में एक डिस्पैचरटेमर बना रहा था और टिक इवेंट की सदस्यता ले रहा था, यदि आप टाइमर पर नहीं करते हैं - तो आपका फॉर्म मेमोरी में लीक हो जाता है!

इस उदाहरण में आपका आंसू कोड होना चाहिए

timer.Tick -= TimerTickEventHandler;

यह एक विशेष रूप से मुश्किल है क्योंकि आपने WPF फॉर्म के अंदर डिस्पैचरटेमर का उदाहरण बनाया है, इसलिए आपको लगता है कि यह कचरा संग्रह प्रक्रिया द्वारा संभाला जाने वाला एक आंतरिक संदर्भ होगा ... दुर्भाग्य से डिस्पैचरटीमर्स सब्सक्रिप्शन और सेवाओं की एक स्थिर आंतरिक सूची का उपयोग करता है। UI थ्रेड पर अनुरोध, इसलिए संदर्भ स्थिर वर्ग द्वारा 'स्वामित्व' है।


1
ट्रिक हमेशा आपके द्वारा बनाए गए सभी ईवेंट सब्सक्रिप्शन को जारी करने की है। यदि आप इसे आपके लिए करने वाले फ़ॉर्म पर भरोसा करना शुरू करते हैं, तो आप सुनिश्चित कर सकते हैं कि आप इसकी आदत में पड़ जाएंगे और एक दिन कहीं एक घटना जारी करना भूल जाएंगे जहाँ इसे करने की आवश्यकता है।
जेसन विलियम्स

3
वहाँ कमजोर संदर्भ घटनाओं के लिए एक एमएस-कनेक्ट सुझाव है यहाँ जो इस समस्या का समाधान होगा, हालांकि मेरी राय में हम सिर्फ पूरी तरह से अविश्वसनीय रूप से गरीब घटना मॉडल एक कमजोर युग्मित एक साथ, टैक्सी द्वारा प्रयोग किया जाता है कि जैसे प्रतिस्थापित करना चाहिए।
ब्लूराजा - डैनी पफ्लुगुएफ्ट

+1 मुझसे, धन्यवाद! खैर, कोड समीक्षा कार्य के लिए कोई धन्यवाद मुझे नहीं करना था!
बॉब डेनी

@ BlueRaja-DannyPflughoeft कमजोर घटनाओं के साथ आपके पास एक और गेटा है - आप लैम्ब्डा की सदस्यता नहीं ले सकते। आप लिख नहीं सकतेtimer.Tick += (s, e,) => { Console.WriteLine(s); }
आर्क-कुन

@ आर्क-कुन हाँ लंबोदर ने इसे और भी कठिन बना दिया है, आपको अपने लंबो को एक चर में सहेजना होगा और इसे अपने फाड़ कोड में उपयोग करना होगा। लिंडा के लेखन की सादगी को नष्ट कर देता है ना?
टिमोथी वाल्टर्स

63

हो सकता है कि वास्तव में एक गोटा न हो क्योंकि व्यवहार MSDN में स्पष्ट रूप से लिखा गया है, लेकिन मेरी गर्दन एक बार टूट गई है क्योंकि मैंने इसे काउंटर-सहज ज्ञान युक्त पाया है:

Image image = System.Drawing.Image.FromFile("nice.pic");

यह आदमी छोड़ता है "nice.pic" फ़ाइल को तब तक लॉक करता है जब तक कि छवि का निपटान नहीं हो जाता। उस समय मैंने इसका सामना किया था, हालांकि यह मक्खी पर आइकन लोड करने के लिए अच्छा होगा और मुझे एहसास नहीं हुआ (पहली बार में) मैंने दर्जनों खुली और लॉक की गई फ़ाइलों के साथ समाप्त किया! छवि इस बात पर नज़र रखती है कि उसने फ़ाइल कहाँ से लोड की थी ...

इसे कैसे हल करें? मैंने सोचा कि एक लाइनर काम करेगा। मैं एक अतिरिक्त पैरामीटर की उम्मीद करता FromFile()था, लेकिन कोई भी नहीं था, इसलिए मैंने यह लिखा ...

using (Stream fs = new FileStream("nice.pic", FileMode.Open, FileAccess.Read))
{
    image = System.Drawing.Image.FromStream(fs);
}

10
मैं मानता हूं कि इस व्यवहार का कोई मतलब नहीं है। मुझे इसके लिए "यह व्यवहार डिज़ाइन द्वारा है" के अलावा कोई स्पष्टीकरण नहीं मिल रहा है।
मुसैनेसिस

1
ओह, और इस वर्कअराउंड के बारे में बहुत अच्छा है यदि आप Image.ToStream को कॉल करने का प्रयास करते हैं (मैं हाथ से सटीक नाम भूल जाता हूं) बाद में यह काम नहीं करेगा।
जोशुआ

55
कुछ कोड की जाँच करने की आवश्यकता है। BRB।
एबेन स्कोव पेडरसेन

7
@EsbenSkovPedersen इतनी सरल लेकिन मजेदार और सूखी टिप्पणी। मेरा दिन बना दिया।
इनशीर

51

यदि आप ASP.NET की गणना करते हैं, तो मैं कहूंगा कि वेबफॉर्म जीवनचक्र मेरे लिए बहुत बड़ा है। मैंने खराब लिखे गए वेबफॉर्म कोड को डिबग करते हुए अनगिनत घंटे बिताए हैं, सिर्फ इसलिए कि बहुत सारे डेवलपर्स को वास्तव में समझ में नहीं आता है कि कब कौन सा इवेंट हैंडलर (मुझे शामिल किया गया, दुख की बात है)।


26
यही कारण है कि मैं MVC में चला गया ... सिरदर्द देखने ...
23

29
विशेष रूप से ASP.NET गोचरों के लिए समर्पित एक अन्य प्रश्न था (वांछनीय रूप से)। ASP.NET की मूल अवधारणा (वेब ​​ऐप बनाने वाले को डेवलपर के लिए विंडोज़ ऐप्स की तरह लगते हैं) बहुत बुरी तरह से गुमराह किया गया है, मुझे यकीन नहीं है कि यह "गोच" के रूप में भी गिना जाता है।
MusiGenesis

1
MusiGenesis मैं चाहता हूं कि मैं आपकी टिप्पणी को सौ बार वोट कर सकूं।
csauve

3
@MusiGenesis यह अब गुमराह लगता है, लेकिन उस समय, लोग अपने वेब अनुप्रयोगों (मुख्य शब्द - ASP.NET WebForms वास्तव में एक ब्लॉग की मेजबानी करने के लिए डिज़ाइन नहीं किए गए थे) को अपने विंडोज़ अनुप्रयोगों के समान व्यवहार करने के लिए चाहते थे। यह केवल अपेक्षाकृत हाल ही में बदल गया है और बहुत से लोग अभी भी "काफी नहीं हैं"। पूरी समस्या यह थी कि अमूर्त रास्ता बहुत अधिक लीक था - वेब एक डेस्कटॉप अनुप्रयोग की तरह व्यवहार नहीं करता था, इसलिए यह लगभग सभी में भ्रम की स्थिति पैदा करता है।
लुअन

1
विडंबना यह है कि ASP.NET के बारे में मैंने जो पहली चीज़ देखी थी, वह Microsoft का एक वीडियो था जिसमें दिखाया गया था कि आप कितनी आसानी से ASP.NET का उपयोग करके ब्लॉग साइट बना सकते हैं!
मूसीगैनेसिस

51

अतिभारित == ऑपरेटर और अनपेड कंटेनर (सरणी विशेषज्ञ, डेटासेट, आदि):

string my = "my ";
Debug.Assert(my+"string" == "my string"); //true

var a = new ArrayList();
a.Add(my+"string");
a.Add("my string");

// uses ==(object) instead of ==(string)
Debug.Assert(a[1] == "my string"); // true, due to interning magic
Debug.Assert(a[0] == "my string"); // false

समाधान?

  • हमेशा उपयोग करें string.Equals(a, b)जब आप स्ट्रिंग प्रकारों की तुलना कर रहे हैं

  • जेनेरिक का उपयोग करके List<string>यह सुनिश्चित करना कि दोनों ऑपरेंड स्ट्रिंग्स हैं।


6
आपको वहां अतिरिक्त स्थान मिला है, जो इसे सभी गलत बनाता है - लेकिन यदि आप रिक्त स्थान को बाहर निकालते हैं, तो अंतिम पंक्ति अभी भी सही होगी क्योंकि "मेरा" + "स्ट्रिंग" अभी भी एक स्थिर है।
जॉन स्कीट

1
एसीके! आप सही हैं :) ठीक है, मैंने थोड़ा संपादित किया।
जिमी

इस तरह के उपयोगों पर एक चेतावनी उत्पन्न होती है।
चक्रित

11
हां, क्लास ऑब्जेक्ट में सी # भाषा के साथ सबसे बड़ी खामियों में से एक == ऑपरेटर है। उन्होंने हमें ReferenceEquals का उपयोग करने के लिए मजबूर करना चाहिए था।
इरिक्कलेन

2
शुक्र है कि 2.0 के बाद से हमारे पास जेनेरिक है। अगर आप ArrayList के बजाय ऊपर दिए उदाहरण में List <string> का उपयोग कर रहे हैं, तो इस बारे में चिंता करने की कम है। इसके अलावा, हम इसे से प्रदर्शन प्राप्त किया है, याय! मैं हमेशा हमारे विरासत कोड में ArrayLists के पुराने संदर्भों को निकाल रहा हूं।
जोएलसीसी

48
[Serializable]
class Hello
{
    readonly object accountsLock = new object();
}

//Do stuff to deserialize Hello with BinaryFormatter
//and now... accountsLock == null ;)

मोरल ऑफ़ द स्टोरी: किसी ऑब्जेक्ट को डीसर्विलाइज़ करते समय फ़ील्ड इनिशियलाइज़र नहीं चलाए जाते हैं


8
हां, मैं डिफ़ॉल्ट कंस्ट्रक्टर को न चलाने के लिए .NET सीरियलाइजेशन से नफरत करता हूं। काश, किसी भी निर्माता को बुलाए बिना किसी वस्तु का निर्माण असंभव था, लेकिन अफसोस ऐसा नहीं है।
रोमन स्टार्कोव

45

DateTime.ToString ("dd / MM / yyyy") ; यह वास्तव में होगा नहीं हमेशा आप dd / mm / yyyy लेकिन इसके बजाय यह आप कहीं भी हों पर निर्भर करता है को ध्यान में क्षेत्रीय सेटिंग लेने के लिए और अपनी तिथि विभाजक का स्थान ले लेगा दे। तो आपको dd-MM-yyyy या कुछ समान मिल सकता है।

ऐसा करने का सही तरीका DateTime.ToString ("dd '/' MM '/' yyyy") का उपयोग करना है;


DateTime.ToString ("r") को RFC1123 में बदलना है, जो GMT का उपयोग करता है। GMT UTC से एक सेकंड के एक अंश के भीतर है, और फिर भी "r" प्रारूप निर्दिष्ट करने वाला UTC में परिवर्तित नहीं होता है , भले ही प्रश्न में DateTime स्थानीय के रूप में निर्दिष्ट किया गया हो।

यह निम्नलिखित गोछा में परिणाम करता है (यह निर्भर करता है कि आपका स्थानीय समय UTC से कितना दूर है):

DateTime.Parse("Tue, 06 Sep 2011 16:35:12 GMT").ToString("r")
>              "Tue, 06 Sep 2011 17:35:12 GMT"

ओह!


19
मिमी से बदलकर MM - मिमी मिनट है, और MM महीने है। एक और गेटा, मुझे लगता है ...
कोबी

1
मैं देख सकता था कि यह कैसे हो सकता है यदि आप इसे नहीं जानते (मैं नहीं था ...) लेकिन मैं यह पता लगाने की कोशिश कर रहा हूं कि आप उस व्यवहार को कब चाहेंगे, जहां आप विशेष रूप से एक तिथि प्रिंट करने की कोशिश कर रहे हैं आपकी क्षेत्रीय सेटिंग्स से क्या मेल नहीं खाता है।
बेस्काका

6
@Beska: क्योंकि आप एक फ़ाइल को लिख रहे हैं, जिसे एक विशिष्ट प्रारूप में निर्दिष्ट तिथि प्रारूप के साथ होना चाहिए।
GvS

11
मेरी राय है कि स्थानीयकृत होने वाली चूक अन्य तरीकों से खराब है। कम से कम डेवलपर ने स्थानीयकरण की अनदेखी की पूरी तरह से कोड मशीनों पर काम करता है स्थानीयकृत अलग। इस तरह, कोड शायद काम नहीं करता है।
जोशुआ

32
वास्तव में मेरा मानना ​​है कि ऐसा करने का सही तरीका हैDateTime.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture);
ब्लूराजा - डैनी पफ्लुगुएफ्ट

44

मैंने देखा कि यह दूसरे दिन पोस्ट किया गया था, और मुझे लगता है कि यह बहुत अस्पष्ट है, और उन लोगों के लिए दर्दनाक है जो नहीं जानते हैं

int x = 0;
x = x++;
return x;

जैसा कि 0 वापस आएगा और 1 नहीं, जैसा कि सबसे अधिक उम्मीद होगी


37
मुझे उम्मीद है कि वास्तव में लोगों को नहीं काटेंगे - मुझे वास्तव में उम्मीद है कि वे इसे पहली जगह में नहीं लिखेंगे! (यह वैसे भी दिलचस्प है।)
जॉन स्कीट

12
मुझे नहीं लगता कि यह बहुत अस्पष्ट है ...
क्रिस मैरास्टी-जॉर्ज

10
कम से कम, सी # में, परिणाम परिभाषित किए जाते हैं, यदि अप्रत्याशित हो। C ++ में, यह 0 या 1, या प्रोग्राम समाप्ति सहित कोई अन्य परिणाम हो सकता है!
जेम्स कर्रान

7
यह एक गोच नहीं है; x = x ++ -> x = x, फिर वेतन वृद्धि x .... x = ++ x -> वेतन वृद्धि x तब x = x
केविन

28
@ केविन: मुझे नहीं लगता कि यह इतना सरल है। अगर x = x ++ x ++ के बाद x + x के बराबर था, तो परिणाम x = 1. होगा। इसके बजाय, मुझे लगता है कि क्या होता है सबसे पहले बराबर चिह्न के दाईं ओर अभिव्यक्ति का मूल्यांकन किया जाता है (0 दे रही है), फिर x है वेतन वृद्धि (x = 1 दे रही है), और अंत में असाइनमेंट किया जाता है (एक बार फिर से x = 0 देते हुए)।
टिम गुडमैन

39

मुझे इस पार्टी में थोड़ी देर हो गई है, लेकिन मेरे पास दो बैच हैं, जिन्होंने हाल ही में मुझे काट लिया है:

दिनांक समय संकल्प

टिक्स की संपत्ति एक सेकंड (100 नैनोसेकंड ब्लॉक) के 10 मिलियनवें हिस्से में समय को मापती है, हालांकि संकल्प 100 नैनोसेकंड नहीं है, यह लगभग 15ms है।

यह कोड:

long now = DateTime.Now.Ticks;
for (int i = 0; i < 10; i++)
{
    System.Threading.Thread.Sleep(1);
    Console.WriteLine(DateTime.Now.Ticks - now);
}

आपको (उदाहरण के लिए) का आउटपुट देगा:

0
0
0
0
0
0
0
156254
156254
156254

इसी तरह, यदि आप DateTime.Now.Millisecond को देखते हैं, तो आपको 15.625ms: 15, 31, 46, आदि के गोल चक्र में मान मिलेंगे।

यह विशेष व्यवहार सिस्टम से सिस्टम में भिन्न होता है , लेकिन इस तारीख / समय एपीआई में अन्य रिज़ॉल्यूशन-संबंधित गोच होते हैं


Path.Combine

फ़ाइल पथ को संयोजित करने का एक शानदार तरीका है, लेकिन यह हमेशा उस तरह से व्यवहार नहीं करता है जैसा आप अपेक्षा करते हैं।

यदि दूसरा पैरामीटर किसी \वर्ण से शुरू होता है , तो यह आपको पूर्ण पथ नहीं देगा:

यह कोड:

string prefix1 = "C:\\MyFolder\\MySubFolder";
string prefix2 = "C:\\MyFolder\\MySubFolder\\";
string suffix1 = "log\\";
string suffix2 = "\\log\\";

Console.WriteLine(Path.Combine(prefix1, suffix1));
Console.WriteLine(Path.Combine(prefix1, suffix2));
Console.WriteLine(Path.Combine(prefix2, suffix1));
Console.WriteLine(Path.Combine(prefix2, suffix2));

आपको यह आउटपुट देता है:

C:\MyFolder\MySubFolder\log\
\log\
C:\MyFolder\MySubFolder\log\
\log\

17
~ 15ms के अंतराल में समय की मात्रा का ठहराव अंतर्निहित समय तंत्र में सटीकता की कमी के कारण नहीं है (मैंने पहले इस पर विस्तार से ध्यान नहीं दिया)। ऐसा इसलिए है क्योंकि आपका ऐप मल्टी-टास्किंग ओएस के अंदर चल रहा है। विंडोज आपके ऐप के साथ हर 15ms या तो चेक करता है, और यह बहुत कम समय के स्लाइस के दौरान मिलता है, आपका ऐप उन सभी संदेशों को प्रोसेस करता है जो आपके पिछले स्लाइस के बाद से कतारबद्ध थे। उस स्लाइस के भीतर आपके सभी कॉल ठीक उसी समय वापस आ जाते हैं क्योंकि वे सभी प्रभावी रूप से एक ही समय में बने होते हैं।
मुशीनेसिस जूल

2
@MusiGenesis: मुझे पता है (अब) यह कैसे काम करता है, लेकिन यह मुझे ऐसा सटीक उपाय लगता है जो वास्तव में सटीक नहीं है। यह कहना पसंद है कि मैं नैनोमीटर में अपनी ऊंचाई जानता हूं जब वास्तव में मैं इसे केवल निकटतम दस मिलियन तक ले जा रहा हूं।
दामोविसा

7
डेटाइम एक टिक तक संग्रहीत करने में काफी सक्षम है; यह DateTime.Now है जो उस सटीकता का उपयोग नहीं कर रहा है।
रुबेन

16
अतिरिक्त '\' कई यूनिक्स / मैक / लिनक्स लोगों के लिए एक गोच है। विंडोज में, अगर कोई अग्रणी '\' है, तो इसका मतलब है कि हम ड्राइव की जड़ पर जाना चाहते हैं (यानी C :) इसे CDकमांड में देखें कि मेरा क्या मतलब है .... 1) गोटो C:\Windows\System322) टाइप CD \Users3) वाह! अब आप C:\Users... आईटी पर हैं? ... Path.Combine (@ "C: \ Windows \ System32", @ "\ उपयोगकर्ता") को वापस \Users[current_drive_here]:\Users
लौटना

8
'नींद ’के बिना भी यह उसी तरह से प्रदर्शन करता है। यह हर 15 एमएस निर्धारित किया जा रहा अनुप्रयोग के साथ कुछ नहीं करना है। DateTime.UtcNow, GetSystemTimeAsFileTime द्वारा बुलाए गए मूल फ़ंक्शन में खराब रिज़ॉल्यूशन दिखाई देता है।
जिम्बो

38

जब आप एक प्रक्रिया शुरू करते हैं (System.Diagnostics का उपयोग करके) जो कंसोल को लिखती है, लेकिन आपने कभी कंसोल नहीं पढ़ा। धारा, आउटपुट की एक निश्चित मात्रा के बाद आपका ऐप लटका हुआ दिखाई देगा।


3
वही तब भी हो सकता है जब आप स्टडआउट और स्टडर को पुनर्निर्देशित करते हैं और क्रम में दो रीडऑन कॉल का उपयोग करते हैं। स्टडआउट और स्टॉडर दोनों की सुरक्षित हैंडलिंग के लिए आपको उनमें से प्रत्येक के लिए एक रीड थ्रेड बनाना होगा।
सेबेस्टियन एम

34

Linq-To-Sql में कोई ऑपरेटर शॉर्टकट नहीं

देखें यहाँ

संक्षेप में, Linq-To-Sql क्वेरी के सशर्त खंड के अंदर, आप सशर्त शॉर्टकट जैसे कि ||और &&अशक्त संदर्भ अपवादों से बचने के लिए उपयोग नहीं कर सकते हैं; Linq-To-Sql OR या AND दोनों पक्षों का मूल्यांकन करता है, भले ही पहली शर्त दूसरी स्थिति का मूल्यांकन करने की आवश्यकता को मानती हो!


8
टीआईएल। BRB, कुछ सौ LINQ प्रश्नों का पुनः अनुकूलन ...
tsilb

30

वर्चुअल विधियों के साथ डिफ़ॉल्ट मापदंडों का उपयोग करना

abstract class Base
{
    public virtual void foo(string s = "base") { Console.WriteLine("base " + s); }
}

class Derived : Base
{
    public override void foo(string s = "derived") { Console.WriteLine("derived " + s); }
}

...

Base b = new Derived();
b.foo();

आउटपुट:
व्युत्पन्न आधार


10
अजीब, मैंने सोचा कि यह पूरी तरह से स्पष्ट है। यदि घोषित प्रकार है Base, तो कंपाइलर को डिफ़ॉल्ट मान प्राप्त होना चाहिए या नहीं Base? मैंने सोचा होगा कि यह थोड़ा और अधिक है कि यदि घोषित प्रकार व्युत्पन्न प्रकार है, भले ही आधार विधि कहा जाता है, तो डिफ़ॉल्ट मान भिन्न हो सकता है ।
टिमवी

1
किसी विधि के कार्यान्वयन से दूसरे कार्यान्वयन का डिफ़ॉल्ट मान क्यों मिलेगा?
स्टाफ़ल

1
@staafl डिफ़ॉल्ट तर्कों को संकलन-समय पर हल किया जाता है, रनटाइम पर नहीं।
फ्रेडओवरफ़्लो

1
मैं कहूंगा कि यह गोच सामान्य रूप से डिफ़ॉल्ट पैरामीटर है - लोगों को अक्सर एहसास नहीं होता है कि वे रन-टाइम के बजाय संकलन-समय पर हल हो गए हैं।
लुआण

4
@FredOverflow, मेरा प्रश्न वैचारिक था। यद्यपि व्यवहार समझ में आता है कि यह कार्यान्वयन के लिए गलत है, लेकिन यह अनपेक्षित और त्रुटियों का एक संभावित स्रोत है। IMHO C # कंपाइलर को ओवरराइड करते समय डिफ़ॉल्ट पैरामीटर मान बदलने की अनुमति नहीं देनी चाहिए।
स्टैफ्ल

27

परस्पर संग्रह में मूल्य वस्तुएं

struct Point { ... }
List<Point> mypoints = ...;

mypoints[i].x = 10;

कोई प्रभाव नहीं है।

mypoints[i]किसी Pointमान ऑब्जेक्ट की प्रतिलिपि देता है । C # खुशी से आपको प्रतिलिपि के एक क्षेत्र को संशोधित करने देता है। चुपचाप कुछ नहीं कर रहा।


अद्यतन: यह C # 3.0 में तय किया गया प्रतीत होता है:

Cannot modify the return value of 'System.Collections.Generic.List<Foo>.this[int]' because it is not a variable

6
मैं देख सकता हूं कि यह भ्रमित क्यों है, यह देखते हुए कि यह वास्तव में सरणियों (आपके उत्तर के विपरीत) के साथ काम करता है, लेकिन सूची <बिंदु> जैसे अन्य गतिशील संग्रह के साथ नहीं।
लास वी। कार्लसन

2
आप सही हे। धन्यवाद। मैंने अपना उत्तर तय कर लिया :)। arr[i].attr=सरणियों के लिए विशेष वाक्यविन्यास है जिसे आप पुस्तकालय कंटेनरों में कोड नहीं कर सकते हैं? (? (<value अभिव्यक्ति>) क्यों है। attr = <expr> सभी के लिए अनुमति दी गई है? क्या यह कभी समझ में आ सकता है?
Bjarke Ebert

1
@Bjarke Ebert: कुछ मामले हैं जहां यह समझ में आता है, लेकिन दुर्भाग्य से कंपाइलर के लिए उन लोगों की पहचान करने और उन्हें अनुमति देने का कोई तरीका नहीं है। नमूना उपयोग का परिदृश्य: एक अपरिवर्तनीय संरचना जो "घुमाव / फ्लिप" संकेतक के साथ एक वर्ग दो आयामी सरणी का संदर्भ रखती है। संरचना स्वयं अपरिवर्तनीय होगी, इसलिए केवल पढ़ने के लिए उदाहरण के एक तत्व के लिए लिखना ठीक होना चाहिए, लेकिन संकलक को यह नहीं पता होगा कि संपत्ति सेटर वास्तव में संरचना लिखने के लिए नहीं जा रहा है, और इस तरह यह अनुमति नहीं देगा ।
सुपरकैट

25

शायद सबसे खराब नहीं है, लेकिन नेट फ्रेमवर्क के कुछ हिस्से डिग्री का उपयोग करते हैं, जबकि अन्य रेडियन का उपयोग करते हैं (और इंटैलिजेंस के साथ दिखाई देने वाला प्रलेखन आपको कभी नहीं बताता है, जिसे जानने के लिए आपको MSDN पर जाना होगा)

Angleइसके बजाय एक वर्ग होने से सभी को बचा जा सकता था ...


मुझे आश्चर्य है कि यह बहुत सारे अपवित्र हैं, मेरे विचार से अन्य
गोच

22

C / C ++ प्रोग्रामर के लिए, C # के लिए संक्रमण एक प्राकृतिक है। हालाँकि, सबसे बड़ा गोचा मैंने व्यक्तिगत रूप से चलाया है (और अन्य लोगों के साथ एक ही परिवर्तन करते हुए देखा है) सी # में कक्षाओं और संरचनाओं के बीच के अंतर को पूरी तरह से नहीं समझ रहा है।

सी ++ में, कक्षाएं और संरचनाएं समान हैं; वे केवल डिफ़ॉल्ट दृश्यता में भिन्न होते हैं, जहां कक्षाएं निजी दृश्यता के लिए डिफ़ॉल्ट होती हैं और सार्वजनिक दृश्यता के लिए डिफ़ॉल्ट डिफ़ॉल्ट होती हैं। C ++ में, यह वर्ग परिभाषा है

    class A
    {
    public:
        int i;
    };

कार्यात्मक रूप से इस संरचनात्मक परिभाषा के समतुल्य है।

    struct A
    {
        int i;
    };

C # में, हालांकि, कक्षाएं संदर्भ प्रकार हैं जबकि संरचना मूल्य प्रकार हैं। यह एक बड़ा बनाता है (1) दूसरे पर एक का उपयोग करने का निर्णय लेने में, (2) परीक्षण वस्तु समानता, (3) प्रदर्शन (जैसे, मुक्केबाजी / अनबॉक्सिंग), आदि में अंतर होता है।

वेब पर दोनों के बीच के अंतर से संबंधित सभी प्रकार की जानकारी है (उदाहरण के लिए, यहां )। मैं किसी को भी C # के लिए संक्रमण करने के लिए अत्यधिक प्रोत्साहित करूंगा, कम से कम मतभेदों और उनके निहितार्थों के बारे में काम करने का ज्ञान होगा।


13
तो, सबसे खराब गोचा लोग भाषा को सीखने से पहले इसे इस्तेमाल करने के लिए समय निकालने की जहमत नहीं उठा रहे हैं?
ब्लूराजा - डैनी पफ्लुगुएट

3
@ BlueRaja-DannyPflughoeft और अधिक स्पष्ट रूप से समान भाषाओं के क्लासिक गोचा की तरह - वे बहुत समान खोजशब्दों और कई मामलों में वाक्यविन्यास का उपयोग करते हैं, लेकिन बहुत अलग तरीके से काम करते हैं।
लुआण

19

कचरा संग्रह और निपटान ()। हालाँकि आपको मेमोरी खाली करने के लिए कुछ भी करने की ज़रूरत नहीं है, फिर भी आपको डिस्पोज़ () के माध्यम से संसाधनों को खाली करना होगा । जब आप WinForms का उपयोग कर रहे हों, या किसी भी तरह से वस्तुओं को ट्रैक कर रहे हों, तो यह भूल जाना बहुत आसान बात है।


2
उपयोग () ब्लॉक बड़े करीने से इस समस्या को हल करता है। जब भी आप डिस्पोज़ करने के लिए कॉल देखते हैं, तो आप तुरंत (और) का उपयोग करने के लिए सुरक्षित रूप से रिफ्लेक्टर कर सकते हैं।
जेरेमी फ्रीy

5
मुझे लगता है कि चिंता का विषय था को लागू करने को सही ढंग से IDisposable।
मार्क ब्रैकेट

4
दूसरी ओर, उपयोग () आदत आपको अप्रत्याशित रूप से काट सकती है, जैसे कि PInvoke के साथ काम करते समय। आप कुछ ऐसा नहीं करना चाहते जिसे एपीआई अभी भी संदर्भित कर रहा है।
MusiGenesis

3
आईडिसेप्‍टली को सही ढंग से लागू करना बहुत कठिन है और यहां तक ​​कि मुझे इस पर मिलने वाली सबसे अच्‍छी सलाह को भी समझना (.NET फ्रेमवर्क गाइडलाइंस) तब तक लागू करने के लिए भ्रामक हो सकती है जब तक कि आप अंत में "इसे प्राप्त नहीं" करते हैं।
क्विबल्शोम

1
सबसे अच्छी सलाह जो मुझे आईडिसेप्यूटिक पर मिली है वह स्टीफन क्लीरी से आई है, जिसमें तीन आसान नियम और आईडीस्रोपी पर
रोमन स्टार्कोव

19

लागू करता है IList

लेकिन इसे लागू नहीं करते। जब आप ऐड कहते हैं, तो यह आपको बताता है कि यह काम नहीं करता है। तो एक वर्ग एक इंटरफ़ेस को लागू क्यों करता है जब वह इसका समर्थन नहीं कर सकता है?

संकलन, लेकिन काम नहीं करता है:

IList<int> myList = new int[] { 1, 2, 4 };
myList.Add(5);

हमारे पास यह मुद्दा बहुत है, क्योंकि धारावाहिक (डब्ल्यूसीएफ) सभी ILists को सरणियों में बदल देता है और हमें रनटाइम त्रुटियां मिलती हैं।


8
IMHO, समस्या यह है कि Microsoft के पास संग्रह के लिए पर्याप्त इंटरफेस नहीं है। IMHO, इसमें iEnumerable, iMultipassEnumerable होना चाहिए (Reset का समर्थन करता है, और कई पास का मिलान होगा, इसकी गारंटी देता है), iLiveEnumerable (संग्रह आंशिक रूप से परिभाषित शब्दार्थ होगा यदि संग्रह में परिवर्तन होता है - परिवर्तन में हो सकता है या प्रकट नहीं हो सकता है, लेकिन इसका कारण नहीं होना चाहिए। फर्जी परिणाम या अपवाद), iReadIndexable, iReadWriteIndexable, आदि। क्योंकि इंटरफेस अन्य इंटरफेस को "इनहेरिट" कर सकता है, इससे कोई अतिरिक्त काम नहीं होगा, यदि कोई है (तो यह Notmmplemented स्टब्स को बचाएगा)।
सुपरकैट

@ सुपरकैट, जो शुरुआती और कुछ लंबे समय के कोडर्स के लिए नरक के रूप में भ्रामक होगा। मुझे लगता है कि .NET संग्रह और उनके इंटरफेस अद्भुत रूप से सुरुचिपूर्ण हैं। लेकिन मैं आपकी विनम्रता की सराहना करता हूं। ;)
जॉर्डन

@Jordan: ऊपर लिख के बाद से, मैंने तय कर लिया है कि एक बेहतर दृष्टिकोण दोनों के लिए हो गया होता गया है IEnumerable<T>और IEnumerator<T>एक समर्थन Featuresअच्छी तरह से कुछ "वैकल्पिक" तरीकों जिसका उपयोगिता क्या "सुविधाओं" सूचना के द्वारा निर्धारित किया जाएगा के रूप में के रूप में संपत्ति। मैं अपने मुख्य बिंदु से खड़ा हूं, हालांकि, यह है कि ऐसे मामले हैं जहां कोड प्राप्त करने वाले IEnumerable<T>को IEnumerable<T>प्रदान करने की तुलना में मजबूत वादों की आवश्यकता होगी । कॉलिंग ToListएक प्राप्त होते हैं IEnumerable<T>कि इस तरह के वादे की पुष्टि की, लेकिन कई मामलों में बेकार में महंगा हो जाएगा। मैं कहता हूं कि ऐसा होना चाहिए ...
सुपरकैट

... एक साधन जिसके द्वारा कोड प्राप्त किया IEnumerable<T>जा सकता है यदि आवश्यक हो तो सामग्री की एक प्रतिलिपि बना सकता है लेकिन ऐसा करने से बच सकता है।
सुपरकाट

आपका विकल्प बिल्कुल पठनीय नहीं है। जब मैं कोड में एक आईएलस्ट देखता हूं तो मुझे पता है कि मैं एक विशेषता संपत्ति की जांच करने के बजाय क्या काम कर रहा हूं। प्रोग्रामर यह भूल जाते हैं कि कोड की एक महत्वपूर्ण विशेषता यह है कि इसे केवल कंप्यूटर नहीं लोगों द्वारा पढ़ा जा सकता है। .NET संग्रह नाम स्थान आदर्श नहीं है, लेकिन यह अच्छा है, और कभी-कभी सबसे अच्छा समाधान खोजना एक सिद्धांत को अधिक आदर्श रूप से फिट करने का मामला नहीं है। सबसे खराब कोड जो मैंने हर काम किया है, वह कोड था जिसने DRY को आदर्श रूप से फिट करने की कोशिश की। मैंने इसे खंगाल कर फिर से लिखा। यह सिर्फ बुरा कोड था। मैं आपके ढांचे का उपयोग बिल्कुल नहीं करना चाहूंगा।
जॉर्डन

18

foreach छोरों चर गुंजाइश!

var l = new List<Func<string>>();
var strings = new[] { "Lorem" , "ipsum", "dolor", "sit", "amet" };
foreach (var s in strings)
{
    l.Add(() => s);
}

foreach (var a in l)
    Console.WriteLine(a());

पांच "एमेट" को प्रिंट करता है, जबकि निम्नलिखित उदाहरण ठीक काम करता है

var l = new List<Func<string>>();
var strings = new[] { "Lorem" , "ipsum", "dolor", "sit", "amet" };
foreach (var s in strings)
{
    var t = s;
    l.Add(() => t);
}

foreach (var a in l)
    Console.WriteLine(a());

11
यह अनिवार्य रूप से अनाम तरीकों के साथ जॉन के उदाहरण के बराबर है।
मेहरदाद अफश्री

3
सहेजें कि यह फ़ॉरच के साथ और भी अधिक भ्रामक है जहाँ "s" वैरिएबल को स्कोपेड वैरिएबल के साथ मिलाना आसान है। सामान्य रूप से छोरों के साथ सूचकांक चर स्पष्ट रूप से प्रत्येक पुनरावृत्ति के लिए समान है।
मिकको रेंटनें

2


आप अनिवार्य रूप से केवल एक ही चर को बार-बार बिना बदले इसे प्रिंट कर रहे हैं।
जॉर्डन

18

MS SQL सर्वर 1753 से पहले की तारीखों को संभाल नहीं सकता है। गौरतलब है कि यह .NET DateTime.MinDateस्थिरांक के साथ सिंक से बाहर है , जो कि 1/1/1 है। इसलिए यदि आप एक मानसिकता, एक विकृत तारीख (जैसा कि हाल ही में डेटा आयात में मेरे साथ हुआ था) या बस विलियम द विजेता की जन्मतिथि को बचाने की कोशिश करते हैं, तो आप मुश्किल में पड़ने वाले हैं। इसके लिए कोई अंतर्निर्मित वर्कअराउंड नहीं है; यदि आपको 1753 से पहले तारीखों के साथ काम करने की आवश्यकता है, तो आपको अपना वर्कअराउंड लिखना होगा।


17
स्पष्ट रूप से मुझे लगता है कि MS SQL सर्वर के पास यह अधिकार है और .Net गलत है। अगर आप रिसर्च करते हैं तो आपको पता है कि 1751 से पहले की तारीखें कैलेंडर में बदलाव, दिन पूरी तरह से खत्म हो जाने आदि के कारण फंकी हो जाती हैं। अधिकांश आरडीबीएम में कुछ कट ऑफ प्वाइंट होता है। यह आपको एक प्रारंभिक बिंदु देना चाहिए: ancestry.com/learn/library/article.aspx?article=3358
NotMe

11
इसके अलावा, तारीख 1753 है .. जो कि पहली बार था जब हम बिना तारीखों के लगातार कैलेंडर छोड़ रहे थे। एसक्यूएल 2008 ने दिनांक और डेटाइम 2 डेटेटाइप पेश किया, जो 1/1/01 से 12/31/9999 तक की तारीखों को स्वीकार कर सकता है। हालांकि, यदि आप वास्तव में पूर्व 1753 तारीखों की तुलना कर रहे हैं, तो उन प्रकारों का उपयोग करने वाले तारीख की तुलना को संदेह के साथ देखा जाना चाहिए।
NotMe

ओह, सही, 1753, सही, धन्यवाद।
शाऊल बेहार

क्या वास्तव में इस तरह की तारीखों के साथ तारीखों की तुलना करने का कोई मतलब है? मेरा मतलब है, इतिहास चैनल के लिए यह बहुत मायने रखता है, लेकिन मैं खुद को नहीं देखना चाहता हूं कि जिस सप्ताह अमेरिका की खोज की गई थी, उसका सटीक दिन जानना चाहते थे।
कैमिलो मार्टिन

5
जूलियन डे पर विकिपीडिया के माध्यम से आप 1984 में प्रकाशित एक 13 लाइन का बेसिक प्रोग्राम CALJD.BAS पा सकते हैं जो कि लगभग 5000 ईसा पूर्व की तारीख की गणना कर सकता है, खाते में छलांग और 1753 में छोड़ दिए गए दिनों को ले रहा है। इसलिए मैं यह नहीं देखता कि क्यों - आधुनिक "SQL2008 जैसे सिस्टम को खराब करना चाहिए। 15 वीं शताब्दी में आपको सही तिथि प्रतिनिधित्व में कोई दिलचस्पी नहीं हो सकती है, लेकिन अन्य लोग, और हमारे सॉफ़्टवेयर को बग के बिना इसे संभालना चाहिए। एक और मुद्दा लीप सेकंड है। । ।
रोलैंड

18

गंदा Linq कैशिंग गोथा

मेरे प्रश्न को देखें जिसने इस खोज का नेतृत्व किया, और समस्या की खोज करने वाले ब्लॉगर

संक्षेप में, DataContext उन सभी Linq-to-Sql ऑब्जेक्ट्स का कैश रखता है जिन्हें आपने कभी लोड किया है। यदि कोई अन्य व्यक्ति आपके द्वारा पहले लोड किए गए रिकॉर्ड में कोई भी बदलाव करता है, तो आप नवीनतम डेटा प्राप्त नहीं कर पाएंगे, भले ही आप स्पष्ट रूप से रिकॉर्ड को लोड करें!

इसका कारण ObjectTrackingEnabledDataContext पर एक संपत्ति है , जो डिफ़ॉल्ट रूप से सत्य है। यदि आप उस संपत्ति को गलत पर सेट करते हैं, तो रिकॉर्ड को हर बार नए सिरे से लोड किया जाएगा ... लेकिन ... आप SubmitChanges () के साथ उस रिकॉर्ड में कोई भी परिवर्तन जारी नहीं रख सकते।

पकड़ लिया!


Iv बस एक दिन और आधा खर्च किया (और बालों का भार!) नीचे इस BUG का पीछा करते हुए ...
सर्जिकल कोडर

इसे एक संगरोध संघर्ष कहा जाता है और यह अभी भी एक गोच है, भले ही अब इसके आस-पास कुछ निश्चित तरीके हैं, हालांकि वे थोड़ा भारी हैं। DataContext एक बुरा सपना था। O_o
जॉर्डन

17

Stream.Read पर अनुबंध कुछ ऐसा है जो मैंने कई लोगों को यात्रा करते देखा है:

// Read 8 bytes and turn them into a ulong
byte[] data = new byte[8];
stream.Read(data, 0, 8); // <-- WRONG!
ulong data = BitConverter.ToUInt64(data);

यह गलत है इसका कारण यह है कि अधिकांश निर्दिष्ट बाइट्स में Stream.Readपढ़ा जाएगा , लेकिन सिर्फ 1 बाइट पढ़ने के लिए पूरी तरह से स्वतंत्र है, भले ही धारा के अंत से पहले एक और 7 बाइट्स उपलब्ध हों।

यह मदद नहीं करता है कि इतने के लिए इसी तरह इस दिखता है Stream.Writeजो, है गारंटी सभी बाइट्स लिखा है अगर यह कोई अपवाद के साथ देता है। यह भी मदद नहीं करता है कि उपरोक्त कोड लगभग हर समय काम करता है । और निश्चित रूप से यह मदद नहीं करता है कि वास्तव में एन बाइट्स को सही ढंग से पढ़ने के लिए कोई तैयार, सुविधाजनक तरीका नहीं है।

तो, छेद को प्लग करने के लिए, और इसके बारे में जागरूकता बढ़ाने के लिए, यहाँ ऐसा करने का एक सही तरीका का एक उदाहरण है:

    /// <summary>
    /// Attempts to fill the buffer with the specified number of bytes from the
    /// stream. If there are fewer bytes left in the stream than requested then
    /// all available bytes will be read into the buffer.
    /// </summary>
    /// <param name="stream">Stream to read from.</param>
    /// <param name="buffer">Buffer to write the bytes to.</param>
    /// <param name="offset">Offset at which to write the first byte read from
    ///                      the stream.</param>
    /// <param name="length">Number of bytes to read from the stream.</param>
    /// <returns>Number of bytes read from the stream into buffer. This may be
    ///          less than requested, but only if the stream ended before the
    ///          required number of bytes were read.</returns>
    public static int FillBuffer(this Stream stream,
                                 byte[] buffer, int offset, int length)
    {
        int totalRead = 0;
        while (length > 0)
        {
            var read = stream.Read(buffer, offset, length);
            if (read == 0)
                return totalRead;
            offset += read;
            length -= read;
            totalRead += read;
        }
        return totalRead;
    }

    /// <summary>
    /// Attempts to read the specified number of bytes from the stream. If
    /// there are fewer bytes left before the end of the stream, a shorter
    /// (possibly empty) array is returned.
    /// </summary>
    /// <param name="stream">Stream to read from.</param>
    /// <param name="length">Number of bytes to read from the stream.</param>
    public static byte[] Read(this Stream stream, int length)
    {
        byte[] buf = new byte[length];
        int read = stream.FillBuffer(buf, 0, length);
        if (read < length)
            Array.Resize(ref buf, read);
        return buf;
    }

1
या, आपके स्पष्ट उदाहरण में var r = new BinaryReader(stream); ulong data = r.ReadUInt64();:। बाइनरीरेडर की एक FillBufferविधि भी है ...
jimbobmcgee

15

आयोजन

मुझे कभी समझ नहीं आया कि घटनाएं भाषा की विशेषता क्यों होती हैं। वे उपयोग करने के लिए जटिल हैं: आपको कॉल करने से पहले अशक्त की जांच करने की आवश्यकता है, आपको अपंजीकृत (अपने आप को) करने की आवश्यकता है, आप यह पता नहीं लगा सकते हैं कि कौन पंजीकृत है (जैसे: क्या मैंने पंजीकरण किया था?)। पुस्तकालय में सिर्फ एक वर्ग के लिए एक घटना क्यों नहीं है? मूल रूप से एक विशेष List<delegate>?


1
इसके अलावा, मल्टीथ्रेडिंग दर्दनाक है। ये सभी मुद्दे, लेकिन अशक्त बात सीएबी में तय किए गए हैं (जिनकी विशेषताएं वास्तव में सिर्फ भाषा में निर्मित होनी चाहिए) - घटनाओं को वैश्विक रूप से घोषित किया जाता है, और कोई भी विधि खुद को किसी भी घटना का "ग्राहक" घोषित कर सकती है। CAB के साथ मेरा एकमात्र मुद्दा यह है कि वैश्विक ईवेंट नाम एनम के बजाय स्ट्रिंग्स हैं (जो कि अधिक बुद्धिमान एनम द्वारा तय किए जा सकते हैं, जैसे जावा में है, जो स्वाभाविक रूप से स्ट्रिंग्स के रूप में काम करता है!) । सीएबी को स्थापित करना मुश्किल है, लेकिन यहां एक सरल ओपन-सोर्स क्लोन उपलब्ध है
ब्लूराजा - डैनी पफ्लुगुएफ्ट

3
मैं .net घटनाओं के कार्यान्वयन को नापसंद करता हूं। ईवेंट सब्सक्रिप्शन को एक विधि को कॉल करके नियंत्रित किया जाना चाहिए जो सब्सक्रिप्शन को जोड़ता है और एक आईडीसॉपी लौटाता है जो डिस्पोज़ल होने पर, सदस्यता को हटा देगा। एक विशेष निर्माण के लिए "ऐड" और "रिमूव" विधि के संयोजन की कोई आवश्यकता नहीं है, जिसका शब्दार्थ कुछ हद तक नीरस हो सकता है, खासकर अगर कोई एक मल्टीकास्ट प्रतिनिधि को जोड़ने और बाद में निकालने का प्रयास करता है (उदाहरण के लिए "बी" और उसके बाद "एबी" जोड़ें, फिर हटा दें "बी" ("बीए" छोड़कर) और "एबी" (अभी भी "बीए" छोड़ रहा है)। उफ़।
1

@supercat आप फिर से कैसे लिखेंगे button.Click += (s, e) => { Console.WriteLine(s); }?
आर्क-कुन

अगर मैं अन्य घटनाओं से अलग सदस्यता समाप्त करने में सक्षम हो, IEventSubscription clickSubscription = button.SubscribeClick((s,e)=>{Console.WriteLine(s);});और के माध्यम से सदस्यता समाप्त होगा clickSubscription.Dispose();। अगर मेरी वस्तु जीवन भर में सभी सदस्यताएँ रखेगी, MySubscriptions.Add(button.SubscribeClick((s,e)=>{Console.WriteLine(s);}));और फिर MySubscriptions.Dispose()सभी सदस्यताएँ मार देगी ।
सुपरकैट

@ अरक-कुन: उन वस्तुओं को रखने के लिए जो बाहर की सदस्यता को घेरते हैं, एक उपद्रव की तरह लग सकते हैं, लेकिन सदस्यता के बारे में संस्थाओं के रूप में उन्हें एक प्रकार के साथ एकत्र करना संभव होगा जो यह सुनिश्चित कर सके कि वे सभी साफ हो जाएं, जो अन्यथा बहुत मुश्किल है।
सुपरकैट

14

आज मैंने एक बग तय किया जो लंबे समय के लिए अलग था। बग एक सामान्य वर्ग में था जो बहु थ्रेडेड परिदृश्य में उपयोग किया गया था और इंटरस्टेड का उपयोग करके लॉक फ्री सिंक्रोनाइज़ेशन प्रदान करने के लिए एक स्थिर इंट फ़ील्ड का उपयोग किया गया था। बग की वजह से था क्योंकि एक प्रकार के लिए सामान्य वर्ग के प्रत्येक तात्कालिकता का अपना स्वयं का स्थिर है। इसलिए प्रत्येक थ्रेड का अपना स्थिर क्षेत्र होता है और इसका उपयोग लॉक के रूप में नहीं किया जाता था।

class SomeGeneric<T>
{
    public static int i = 0;
}

class Test
{
    public static void main(string[] args)
    {
        SomeGeneric<int>.i = 5;
        SomeGeneric<string>.i = 10;
        Console.WriteLine(SomeGeneric<int>.i);
        Console.WriteLine(SomeGeneric<string>.i);
        Console.WriteLine(SomeGeneric<int>.i);
    }
}

यह 5 10 5 प्रिंट करता है


5
आपके पास एक गैर-जेनेरिक आधार वर्ग हो सकता है, जो स्टेटिक्स को परिभाषित करता है, और इससे जेनेरिक विरासत में मिलता है। हालाँकि मैं इस व्यवहार के लिए C # में कभी नहीं गिरा - मुझे अभी भी कुछ C ++ टेम्पलेट्स के लंबे डिबगिंग घंटे याद हैं ... Eww! :)
पॉलियस

7
अजीब, मुझे लगा कि यह स्पष्ट था। यदि iइसके प्रकार के बारे में सोचना चाहिए तो क्या करना चाहिए T
टिमवी

1
प्रकार पैरामीटर का हिस्सा है TypeSomeGeneric<int>से एक अलग प्रकार है SomeGeneric<string>; इसलिए प्रत्येक का अपना स्वयं काpublic static int i
राडारोब

13

Enumerables का मूल्यांकन एक से अधिक बार किया जा सकता है

जब आप एक आलसी-एन्यूमरेटेड एन्यूमरेबल होंगे तो यह आपको काटेगा और आप इसे दो बार दोहराएंगे और विभिन्न परिणाम प्राप्त करेंगे। (या आपको एक ही परिणाम मिलता है लेकिन यह अनावश्यक रूप से दो बार निष्पादित होता है)

उदाहरण के लिए, एक निश्चित परीक्षण लिखते समय, मुझे तर्क का परीक्षण करने के लिए कुछ अस्थायी फ़ाइलों की आवश्यकता थी:

var files = Enumerable.Range(0, 5)
    .Select(i => Path.GetTempFileName());

foreach (var file in files)
    File.WriteAllText(file, "HELLO WORLD!");

/* ... many lines of codes later ... */

foreach (var file in files)
    File.Delete(file);

मेरे आश्चर्य की कल्पना करो जब File.Delete(file)फेंकता है FileNotFound!!

यहाँ क्या हो रहा है कि filesगणना करने योग्य दो बार पुनरावृत्त हुआ (पहले पुनरावृत्ति से परिणाम आसानी से याद नहीं हैं) और प्रत्येक नए पुनरावृत्ति पर आपको फिर से कॉल करना होगा Path.GetTempFilename()ताकि आपको अस्थायी फ़ाइल नाम का एक अलग सेट मिलेगा।

निस्संदेह, इसका उपयोग करके ToArray()या मान को उत्सुकता से हल करने के लिए समाधान है ToList():

var files = Enumerable.Range(0, 5)
    .Select(i => Path.GetTempFileName())
    .ToArray();

यह तब भी डरावना है जब आप कुछ बहु-थ्रेड कर रहे हैं, जैसे:

foreach (var file in files)
    content = content + File.ReadAllText(file);

और आपको पता है content.Lengthकि सभी लिखने के बाद भी 0 है !! फिर आप सख्ती से जांचना शुरू करते हैं कि आपके पास दौड़ की स्थिति नहीं है .... जब एक घंटे बर्बाद हो गया ... तो आपको पता चला कि यह सिर्फ इतना छोटा सा Enumerable गोचा है जिसे आप भूल गए थे ...।


यह डिजाइन द्वारा है। इसे आस्थगित निष्पादन कहा जाता है। अन्य बातों के अलावा, यह TSQL निर्माण का अनुकरण करने के लिए है। हर बार जब आप एक वर्ग दृश्य से चयन करते हैं तो आपको अलग-अलग परिणाम मिलते हैं। यह चैनिंग की भी अनुमति देता है जो कि SQL सर्वर जैसे दूरस्थ डेटा स्टोर के लिए सहायक है। अन्यथा x.Select.Where.OrderBy डेटाबेस के लिए 3 अलग-अलग कमांड भेजेगा ...
as9876

@ ^ क्या आपने प्रश्न शीर्षक में "गोचचा" शब्द याद किया?
चक्रित

मुझे लगा कि गोचर का मतलब डिजाइनरों का निरीक्षण करना है, न कि कुछ जानबूझकर।
as9876

शायद गैर-पुन: प्रयोज्य IEnumerables के लिए एक और प्रकार होना चाहिए। जैसे, AutoBufferedEnumerable? कोई भी इसे आसानी से लागू कर सकता है। यह गैचा ज्यादातर प्रोग्रामर के ज्ञान की कमी के कारण लगता है, मुझे नहीं लगता कि वर्तमान व्यवहार में कुछ भी गलत है।
एल्ड्रिच कॉनड्रम

13

बस एक अजीब सा मिला जो मुझे थोड़ी देर के लिए डिबग में फंस गया था:

आप बिना किसी अपवाद के फेंकने के लिए अशक्त इंट के लिए शून्य बढ़ा सकते हैं और मूल्य शून्य रहता है।

int? i = null;
i++; // I would have expected an exception but runs fine and stays as null

यह परिणाम है कि कैसे C # अशक्त प्रकारों के लिए परिचालन का लाभ उठाता है। यह थोडा NaN के समान है जो आप इसे फेंकते हैं।
IllidanS4 मोनिका को

10
TextInfo textInfo = Thread.CurrentThread.CurrentCulture.TextInfo;

textInfo.ToTitleCase("hello world!"); //Returns "Hello World!"
textInfo.ToTitleCase("hElLo WoRld!"); //Returns "Hello World!"
textInfo.ToTitleCase("Hello World!"); //Returns "Hello World!"
textInfo.ToTitleCase("HELLO WORLD!"); //Returns "HELLO WORLD!"

हां, यह व्यवहार प्रलेखित है, लेकिन यह निश्चित रूप से इसे सही नहीं बनाता है।


5
मैं असहमत हूं - जब कोई शब्द सभी कैप्स में होता है, तो इसका विशेष अर्थ हो सकता है कि आप शीर्षक मामले के साथ गड़बड़ नहीं करना चाहते हैं, उदाहरण के लिए "यूएसए के राष्ट्रपति" -> "यूएसए के राष्ट्रपति", न कि "राष्ट्रपति" अमेरीका"।
शाऊल बेहर

5
@ शुल: किस मामले में, उन्हें भ्रम से बचने के लिए इसे एक पैरामीटर के रूप में निर्दिष्ट करना चाहिए , क्योंकि मैं कभी भी किसी से भी नहीं मिला हूं, जो समय से पहले इस व्यवहार की उम्मीद करता है - जो इसे एक पकड़ बनाता है !
ब्लूराजा - डैनी पफ्लुघोटे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.