C #: 'कीवर्ड है और Not के लिए जाँच कर रहा है


287

यह एक मूर्खतापूर्ण प्रश्न है, लेकिन आप इस कोड का उपयोग यह जांचने के लिए कर सकते हैं कि क्या कोई विशेष प्रकार है ...

if (child is IContainer) { //....

वहाँ "नहीं" उदाहरण के लिए जाँच करने के लिए एक और अधिक सुंदर तरीका है?

if (!(child is IContainer)) { //A little ugly... silly, yes I know...

//these don't work :)
if (child !is IContainer) {
if (child isnt IContainer) { 
if (child aint IContainer) { 
if (child isnotafreaking IContainer) { 

हाँ, हाँ ... मूर्खतापूर्ण सवाल ...।

क्योंकि कोड कैसा दिखता है, इस पर कुछ सवाल है , यह एक विधि की शुरुआत में सिर्फ एक साधारण रिटर्न है।

public void Update(DocumentPart part) {
    part.Update();
    if (!(DocumentPart is IContainer)) { return; }
    foreach(DocumentPart child in ((IContainer)part).Children) {
       //...etc...

105
मैं व्यक्तिगत रूप से "बच्चे को नोनाफ्रेकिंग ..." पसंद करता हूं। मैं उस कीवर्ड को C # 5
यूसुफ

मुझे यह जानने में दिलचस्पी है कि आप इस स्थिति का क्या उपयोग करेंगे? इस कोड का "और" भाग कैसा दिखता है और क्या आप परीक्षण में उलट नहीं कर सकते? यदि आपका कोड कह रहा है "यदि बच्चा IContainer नहीं है, तो अपवादों को फेंकें" या "यदि बच्चा IContainer नहीं है, तो शायद यह एक IFoo है तो मैं कोशिश करूंगा कि अगला" तब कोई निहित बयान न हो? मुझे शायद कुछ याद आ रहा है।
मार्टिन पेक

1
@MartinPeck, एक और खंड नहीं हो सकता है। यही कारण है कि मैंने इसके लिए खोज की।
जोशुआ वॉल्श

@MartinPeck यहाँ एक नमूना है: if (!(argument is MapsControlViewModel vm)) { return; }- अगर मैं औंधा सकता है और अगर बाकी कोष्ठक को अगर के कोष्ठक के अंदर रखता है, लेकिन तब मुझे क्रिसमस-ट्री कोड मिलेगा, जिसमें विधि के अंत में बहुत सारे समापन कोष्ठक होंगे। यह बहुत कम पठनीय है।
एविव्स

शायद हम क्या सामान्य रूप में की जरूरत है ifnotबयान
डेव Cousineau

जवाबों:


301
if(!(child is IContainer))

जाने के लिए केवल ऑपरेटर है (कोई IsNotऑपरेटर नहीं है)।

आप एक एक्सटेंशन विधि बना सकते हैं जो इसे करती है:

public static bool IsA<T>(this object obj) {
    return obj is T;
}

और फिर इसका उपयोग करें:

if (!child.IsA<IContainer>())

और आप अपने विषय पर अनुसरण कर सकते हैं:

public static bool IsNotAFreaking<T>(this object obj) {
    return !(obj is T);
}

if (child.IsNotAFreaking<IContainer>()) { // ...

अद्यतन (ओपी कोड स्निपेट पर विचार करते हुए):

चूंकि आप वास्तव में बाद में मूल्य डाल रहे हैं, आप asइसके बजाय बस उपयोग कर सकते हैं :

public void Update(DocumentPart part) {
    part.Update();
    IContainer containerPart = part as IContainer;
    if(containerPart == null) return;
    foreach(DocumentPart child in containerPart.Children) { // omit the cast.
       //...etc...

1
ck: मेरा मतलब ऑपरेटरों के अर्थ में है, कोई IsNotबात नहीं है।
मेहरदाद अफश्री

5
हाँ। अगर मैं स्पष्ट नहीं हूं तो मैं मजाक कर रही हूं।
मेहरदाद अफश्री

111

आप इसे इस तरह से कर सकते हैं:

object a = new StreamWriter("c:\\temp\\test.txt");

if (a is TextReader == false)
{
   Console.WriteLine("failed");
}

2
@ फ्रेंक - हाँ, कीवर्ड एक बूलियन देता है, जिसे आप झूठी तुलना कर सकते हैं
cjk

32
@ यह काम करता है क्योंकि isउच्च सापेक्षता है ==। एकमात्र कारण जो आप उपयोग नहीं कर सकते हैं !x is fवह यह है कि इसकी पूर्ववर्तीता कम है !
मेहरदाद आफशरी

मुझे यह पसंद है लेकिन एक चर को पेश करते समय यह सही काम नहीं करता है, भले ही यह होना चाहिए। if (a is TextReader reader == false)"काम" करना चाहिए, लेकिन यह आपको सत्य पथ में चर का उपयोग नहीं करने देगा, यह कहते हुए कि यह आरंभिक नहीं हो सकता है।
डेव कज़िनो

@DaveCousineau - आम तौर पर आप एक वेरिएबल टाइप करते हैं और एक वेरिएबल पेश करते हैं जब आप शुरू किए गए वेरिएबल का उपयोग करना चाहते हैं। मुझे यकीन नहीं है कि यदि टाइपकास्ट विफल हुआ तो चर कैसे उपयोगी होगा। (अस्वीकरण - मुझे "पैटर्न मिलान" सुविधा दोनों खराब नाम और outमापदंडों का उपयोग करते हुए एक कोड गंध के रूप में खराब है )
स्टिंगजैक

@StingyJack कुछ प्रकार की गड़बड़ है जहां सही रास्ते में , चर को एकतरफा माना जाता है। यहां तक ​​कि अगर आप कहते हैं कि if (a is TextReader reader == true)यह लगता है कि चर uninitialized है।
डेव कजिनो

11

सिर्फ दूसरे का उपयोग क्यों नहीं?

if (child is IContainer)
{
  //
}
else
{
  // Do what you want here
}

इसके साफ यह परिचित और सरल?


3
इसके साथ कुछ भी गलत नहीं है - यह सिर्फ एक निपिक सवाल है। मैं एक समारोह से तुरंत बाहर निकलना चाहता था अगर कुछ विशेष प्रकार का नहीं था। मैंने इसे हमेशा के लिए ((बच्चा कुछ है)) हमेशा के लिए कर दिया है, लेकिन मुझे लगा कि मैं सुनिश्चित करूंगा कि बेहतर तरीका नहीं था।
होगोवरे

1
प्रश्न में नमूना कोड के साथ, इसका मतलब खाली होगा यदि ब्रैकेट। यह एक समझदार विकल्प की तरह नहीं है।
एनेव्स

9

जिस तरह से आपके पास यह ठीक है, लेकिन आप "नॉट इंस्टेंस" की जांच करने के लिए "अधिक सुरुचिपूर्ण तरीका" बनाने के लिए विस्तार विधियों का एक सेट बना सकते हैं।

public static bool Is<T>(this object myObject)
{
    return (myObject is T);
}

public static bool IsNot<T>(this object myObject)
{
    return !(myObject is T);
}

तब आप लिख सकते हैं:

if (child.IsNot<IContainer>())
{
    // child is not an IContainer
}

7

यह अभी तक उल्लेख नहीं किया गया है। यह काम करता है और मुझे लगता है कि यह उपयोग करने से बेहतर है!(child is IContainer)

if (part is IContainer is false)
{
    return;
}

isवाक्यविन्यास: expr is constant जहां एक्सपर्ट मूल्यांकन करने के लिए अभिव्यक्ति है, और निरंतर परीक्षण के लिए मूल्य है।


3
इसी तरह आप कर सकते थे if (part as IContainer is null)। ईमानदारी से सुनिश्चित नहीं है कि कौन बेहतर है।
फ्लाईन 1179

5

बदसूरत? मैं असहमत हूं। केवल दूसरा तरीका (मुझे व्यक्तिगत रूप से लगता है कि यह "बदसूरत" है):

var obj = child as IContainer;
if(obj == null)
{
   //child "aint" IContainer
}

@ मेहरदाद - अशक्त? इसे काम करने के लिए सक्षम करेगा, न कि इसका उपयोग किया जाना चाहिए। यह एक कुरूप तरीके का एक उदाहरण मात्र है।
स्टेवेपवेल

@ स्टीवो ३०००: हाँ, लेकिन आपको स्पष्ट रूप से उल्लेख करना चाहिए? है asखंड। obj as intहमेशा एक संकलन समय त्रुटि है।
मेहरदाद अफशरी

@ मेहरदाद - सहमत, बीफ्री ने इसे प्रतिबिंबित करने के लिए अपने पोस्ट को संपादित किया। हमें दे 'int के रूप में obj?'।
स्टीववेवेल १४'४

@ Stevo3000: मुझे नहीं लगता कि इसके साथ कुछ भी गलत है। IContainer को value type के बजाय एक interface जैसा लगता है। बस यह इंगित करना चाहता था कि इसे मूल्य प्रकार पर ध्यान देने की आवश्यकता है और यह हमेशा isप्रपत्र का प्रत्यक्ष अनुवाद नहीं है ।
मेहरदाद अफशरी

आप वैकल्पिक रूप से कर सकते हैं अगर (obj == डिफ़ॉल्ट (IContainer)), जो मान प्रकार और संदर्भ प्रकारों का ध्यान रखेगा
यूसुफ

3

isएक बूलियन परिणाम के लिए ऑपरेटर मूल्यांकन करता है, तो आप कुछ भी कर सकते आप अन्यथा एक bool पर ऐसा करने में सक्षम हो जाएगा। इसे नकारने के लिए यह !ऑपरेटर का उपयोग करता है। आप इसके लिए एक अलग ऑपरेटर क्यों रखना चाहेंगे?


5
यह एक अलग ऑपरेटर नहीं है। मैं सोच रहा था कि क्या कोई ऐसा कीवर्ड है जो मुझे पैरेन्स के अतिरिक्त सेट को छोड़ने देगा। यह एक प्रमुख नाइट-पिक है, लेकिन मैं उत्सुक था।
ह्यूगोवर

ठीक है मैं समझ गया। आपके उदाहरणों से मुझे आभास हुआ कि आप एक नए, समर्पित ऑपरेटर की तलाश में थे।
ब्रायन रासमुसेन

मुझे लगता है कि इस तरह के एक विशेष ऑपरेटर का होना बुरा है, क्योंकि हमारे पास इस तरह से होगा (इस एएनएस को समझाया, वैसे भी), और अगर हमारे पास एक और ऑप था, तो एक ही चीज़ को प्राप्त करने के दो तरीके हैं, भ्रमित हो सकते हैं।
बुद्धी

3

विस्तार पद्धति IsNot<T>वाक्यविन्यास को बढ़ाने का एक अच्छा तरीका है। याद रखो

var container = child as IContainer;
if(container != null)
{
  // do something w/ contianer
}

कुछ करने से बेहतर प्रदर्शन करता है

if(child is IContainer)
{
  var container = child as IContainer;
  // do something w/ container
}

आपके मामले में, इससे कोई फर्क नहीं पड़ता कि आप विधि से लौट रहे हैं। दूसरे शब्दों में, टाइप के लिए चेक और उसके बाद टाइप रूपांतरण दोनों न करने के लिए सावधान रहें।


3

जबकि यह Google के माध्यम से यहां आने वाले लोगों के लिए, कोष्ठकों की समस्या से नहीं बचता है, यह उल्लेख किया जाना चाहिए कि आपके कोड के बाकी हिस्सों को थोड़ा साफ करने के लिए नया सिंटैक्स मौजूद है (C # 7 के रूप में):

if (!(DocumentPart is IContainer container)) { return; }
foreach(DocumentPart child in container.Children) {
    ...

यह डबल-कास्ट, नल-चेक से बचता है, और स्कोप में उपलब्ध वैरिएबल होने से जहां यह शून्य हो सकता है।


2

जबकि आईएस ऑपरेटर आमतौर पर सबसे अच्छा तरीका है, एक विकल्प है जिसे आप कुछ cirumstances में उपयोग कर सकते हैं। आप ऑपरेटर के रूप में उपयोग कर सकते हैं और अशक्त के लिए परीक्षण कर सकते हैं।

MyClass mc = foo as MyClass;
if ( mc == null ) { }
else {}

2

C # 9 (.NET 5 के साथ रिलीज़ होने के लिए) में तार्किक पैटर्न शामिल होंगे and, orऔर not, जो हमें इसे और अधिक सुरुचिपूर्ण ढंग से लिखने की अनुमति देता है:

if (child is not IContainer) { ... }

इसी तरह, इस पैटर्न का उपयोग अशक्त की जाँच के लिए किया जा सकता है:

if (child is not null) { ... }

आप इस परिवर्तन को ट्रैक करने वाले Github मुद्दे पर अधिक जानकारी पा सकते हैं ।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.