2013-02-19 67 views
94

मैं दो System.Drawing.Size संरचनाओं की समानता पर जोर देने की कोशिश कर रहा हूं, और मुझे अपेक्षित जोर विफलता की बजाय प्रारूप अपवाद मिल रहा है।संरचनाओं की तुलना करते समय यह एक प्रारूप अपवाद क्यों फेंकता है?

[TestMethod] 
public void AssertStructs() 
{ 
    var struct1 = new Size(0, 0); 
    var struct2 = new Size(1, 1); 

    //This throws a format exception, "System.FormatException: Input string was not in a correct format." 
    Assert.AreEqual(struct1, struct2, "Failed. Expected {0}, actually it is {1}", struct1, struct2); 

    //This assert fails properly, "Failed. Expected {Width=0, Height=0}, actually it is {Width=1, Height=1}". 
    Assert.AreEqual(struct1, struct2, "Failed. Expected " + struct1 + ", actually it is " + struct2); 
} 

क्या यह इरादा व्यवहार है? क्या मुझसे यहां कुछ गलत हो रहा है?

+0

क्या आपने 'Assert.AreEqual (struct1, struct2, string.Format (" असफल होने की उम्मीद {0} वास्तव में {1} ', struct1.ToString(), struct2.ToString()) है?' – DiskJunky

+0

ठीक काम करता है, हालांकि मैं उत्सुक हूं कि क्यों Assert.AreEqual() संरचना प्रकारों के साथ एक स्ट्रिंग को प्रारूपित नहीं कर सकता है। – Kyle

+0

@ किइल जिज्ञासा से बाहर, यह यूनिट परीक्षण फ्रेमवर्क के सिल्वरलाइट संगत संस्करण के साथ नहीं है, क्या यह है ? मैं इसे उन डीएलएल के साथ पुन: उत्पन्न कर सकता हूं (अभी तक पूर्ण .NET फ्रेमवर्क संस्करण की कोशिश नहीं की है) संपादित करें: कभी भी, पूर्ण लोगों के साथ परीक्षण नहीं किया गया और अभी भी असफल रहा। :) –

उत्तर

100

मुझे यह मिल गया है। और हाँ, यह एक बग है।

समस्या यह है कि string.Format के दो स्तर यहां जा रहे हैं।

पहले स्वरूपण का स्तर है कुछ की तरह:

string template = string.Format("Expected: {0}; Actual: {1}; Message: {2}", 
           expected, actual, message); 

फिर हम पैरामीटर आपके द्वारा बताये गये हैं, उनके साथ string.Format का उपयोग करें:

string finalMessage = string.Format(template, parameters); 

(जाहिर है संस्कृतियों प्रदान की जा रही है, और है कुछ स्वच्छता के प्रकार ... लेकिन पर्याप्त नहीं है।)

यह ठीक दिखता है - जब तक अपेक्षित और वास्तविक मान स्वयं स्ट्रिंग में परिवर्तित होने के बाद ब्रेसिज़ के साथ समाप्त नहीं होते हैं - जो वे Size के लिए करते हैं। उदाहरण के लिए, अपने पहले आकार समाप्त होता है में बदला जा रहा:

{Width=0, Height=0} 

तो स्वरूपण के दूसरे स्तर की तरह कुछ है:

string.Format("Expected: {Width=0, Height=0}; Actual: {Width=1, Height=1 }; " + 
       "Message = Failed expected {0} actually is {1}", struct1, struct2); 

... और वह है क्या नाकाम रहने रहा है। आउच।

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

var x = "{0}"; 
var y = "{1}"; 
Assert.AreEqual<object>(x, y, "What a surprise!", "foo", "bar"); 

परिणाम है:

Assert.AreEqual failed. Expected:<foo>. Actual:<bar>. What a surprise! 

जाहिर टूट, हम के रूप में foo की उम्मीद नहीं थी और न ही वास्तविक मूल्य bar था!

असल में यह एक एसक्यूएल इंजेक्शन हमले की तरह है, लेकिन string.Format के कम डरावनी संदर्भ में है।

एक कामकाज के रूप में, आप string.Format का उपयोग कर सकते हैं क्योंकि स्ट्राइप्लिंगवायरियर सुझाव देता है। यह वास्तविक/अपेक्षित मानों के साथ स्वरूपण के परिणामस्वरूप स्वरूपण के दूसरे स्तर से परहेज करता है।

+0

विस्तृत उत्तर जॉन के लिए धन्यवाद! मैंने स्ट्राइप्लिंगवायरियर्स का उपयोग करके काम खत्म कर दिया। – Kyle

+1

कोई '% * एन' बराबर नहीं है? :( –

+0

क्या किसी ने इसके लिए एक बग रिपोर्ट सबमिट की है? – Kevin

3

मुझे लगता है कि पहला दावा गलत है।

उपयोग इस बजाय:

Assert.AreEqual(struct1, 
       struct2, 
       string.Format("Failed expected {0} actually is {1}", struct1, struct2)); 
+0

प्रलेखन के अनुसार मैं एक प्रारूपित स्ट्रिंग के साथ AreEqual को कॉल करने में सक्षम होना चाहिए। Http://msdn.microsoft.com/en-us/library/ms243436%28v=vs.100%29.aspx, विशेष रूप से पैरामीटर टाइप करें: System.Object [] संदेश स्वरूपण करते समय उपयोग करने के लिए पैरामीटर की एक सरणी। – Kyle

43

मैं तुम्हें एक बग पाया है लगता है।

यह काम करता है (एक ज़ोर अपवाद फेंकता):

var a = 1; 
var b = 2; 
Assert.AreEqual(a, b, "Not equal {0} {1}", a, b); 

और यह काम करता है (संदेश आउटपुट):

var a = new{c=1}; 
var b = new{c=2}; 
Console.WriteLine(string.Format("Not equal {0} {1}", a, b)); 

लेकिन यह काम नहीं करता है (फेंकता एक FormatException):

var a = new{c=1}; 
var b = new{c=2}; 
Assert.AreEqual(a, b, "Not equal {0} {1}", a, b); 

मैं किसी भी कारण से सोच नहीं सकता कि यह व्यवहार की अपेक्षा की जाएगी। मैं एक बग रिपोर्ट जमा करूंगा।

var a = new{c=1}; 
var b = new{c=2}; 
Assert.AreEqual(a, b, string.Format("Not equal {0} {1}", a, b)); 
5

मैं @StriplingWarrior साथ सहमत हैं कि यह वास्तव में कम से कम 2 भार के पर विधि Assert.AreEqual() के साथ एक बग प्रतीत होता है: इस बीच, यहाँ एक समाधान है। जैसा कि StiplingWarrior पहले ही इंगित कर चुका है, निम्नलिखित विफल रहता है;

var a = new { c = 1 }; 
var b = new { c = 2 }; 
Assert.AreEqual(a, b, "Not equal {0} {1}", a, b); 

मैं कोड उपयोग में थोड़ी अधिक स्पष्ट होने पर इस पर थोड़ा प्रयोग कर रहा हूं। निम्नलिखित या तो काम नहीं करता है;

// specify variable data type rather than "var"...no effect, still fails 
Size a = new Size(0, 0); 
Size b = new Size(1, 1); 
Assert.AreEqual(a, b, "Not equal {0} {1}", a, b); 

और

// specify variable data type and name the type on the generic overload of AreEqual()...no effect, still fails 
Size a = new Size(0, 0); 
Size b = new Size(1, 1); 
Assert.AreEqual<Size>(a, b, "Not equal {0} {1}", a, b); 

यह मैं सोच मिला है। सिस्टम। ड्रॉइंग .इज एक संरचना है। वस्तुओं के बारे में क्या? Param सूची निर्दिष्ट करता है कि string संदेश के बाद सूची params object[] है। तकनीकी रूप से, हाँ structs ऑब्जेक्ट्स हैं ... लेकिन विशेष प्रकार वस्तुओं, यानी मूल्य प्रकार। मुझे लगता है कि यह वह जगह है जहां बग झूठ बोलता है। यदि हम Size पर समान उपयोग और संरचना के साथ अपनी स्वयं की वस्तु का उपयोग करते हैं, तो वास्तव में कार्य करता है;

private class MyClass 
{ 
    public MyClass(int width, int height) 
     : base() 
    { Width = width; Height = height; } 

    public int Width { get; set; } 
    public int Height { get; set; } 
} 

[TestMethod] 
public void TestMethod1() 
{ 
    var test1 = new MyClass(0, 0); 
    var test2 = new MyClass(1, 1); 
    Assert.AreEqual(test1, test2, "Show me A [{0}] and B [{1}]", test1, test2); 
} 
+1

समस्या यह नहीं है कि यह 'वर्ग' या' स्ट्रक्चर 'है, लेकिन क्या' ToString' मान में घुंघराले ब्रैकेट होते हैं जो 'स्ट्रिंग' .Format' –