मुझे लगता है कि इंटरफ़ेस (कॉन्ट्रा?)भिन्नता ही उत्तर है, लेकिन सही समाधान नहीं मिल रहा है।

आइए इन वर्गों को प्राप्त करें:

public abstract class Fruit { }
public class Banana : Fruit { }
public class Apple : Fruit { }

public abstract class Picture { }
public class FruitPicture<T> : Picture, Contravariant<T>, Covariant<T> where T : Fruit
{
    T myFruit = null;

    public Type GetFruitType() { return typeof(T); }

    public void AddFruit(T fruit) { this.myFruit = fruit; }
}

public interface Contravariant<in T> { void AddFruit(T model); }
public interface Covariant<out T> { Type GetFruitType(); }

मेरी स्थिति है:

  • मेरे पास केले और सेब का संग्रह पहले से ही शुरू हो चुका है, जैसे कि ये दोनों (लेकिन मैं एक अलग का उपयोग कर सकता हूं):

    Fruit[] myFruits = new Fruit[2]
    {
        new Banana(),
        new Apple()
    };
    
  • मेरे पास चित्रों का एक संग्रह है, जैसे कि ये दोनों:

    Picture[] myPictures = new Picture[2]
    {
        new FruitPicture<Banana>(),
        new FruitPicture<Apple>(),
    };
    

अब, मैं एक बहुत ही सरल काम करना चाहता हूं, लेकिन एक बहुमुखी तरीके से, जिसका अर्थ है कि मैं किसी भी स्विच / आईएफएस से बचना चाहता हूं, जहां मुझे हर बार एक नया फल मिलने पर कोड बदलना होगा और संग्रह में नया फ्रूट पिक्चर दिखाई दे सकता है => मैं अपने संग्रह से .AddFruit() को उचित प्रकार के FruitPicture में लाना चाहता हूं। मैं किसी भी तर्क को काफी हद तक बदल सकता हूं, लेकिन मैं जेनेरिक फ्रूट पिक्चर क्लास रखना चाहता हूं।

मेरे पास सबसे करीब होगा:

foreach(Picture curPicture in myPictures)
{
    foreach (Fruit curFruit in myFruits)
    {
        Covariant<Fruit> fruitType = (Covariant<Fruit>)curPicture;
        if (curFruit.GetType() == fruitType.GetFruitType())
        {
            // what now?
        }
    }
}

धन्यवाद श्रीमान। स्कीट (मजाक करना; तरह का)

0
Demo 23 अक्टूबर 2018, 00:43

1 उत्तर

सबसे बढ़िया उत्तर

चूंकि आपके पास समस्या यह है कि आप संकलन-समय प्रकार-सुरक्षा करना चाहते हैं, लेकिन आप रन-टाइम तक प्रकारों को नहीं जानते हैं, आप dynamic का उपयोग करके निर्णय को रन-टाइम तक बंद कर सकते हैं। मैं जरूरी नहीं कि इसकी सिफारिश कर रहा हूं, सिर्फ यह कह रहा हूं कि यह काम करेगा।

मैंने Covariant इंटरफ़ेस को सामान्य होने की आवश्यकता नहीं होने के कारण बदल दिया क्योंकि इसने प्रकार पैरामीटर का कोई उपयोग नहीं किया। मैंने AddFruit का नाम बदलकर SetFruit कर दिया, क्योंकि इसमें कुछ भी नहीं जोड़ा था, लेकिन इसे बदल दिया गया था।

foreach (var fruit in myFruits) {
    foreach (var picture in myPictures) {
        if (picture is Covariant cov) {
            if (cov.GetFruitType() == fruit.GetType())
                ((dynamic)picture).SetFruit(Convert.ChangeType((dynamic)fruit, cov.GetFruitType()));
        }
    }
}

(dynamic) ChangeType की आवश्यकता है क्योंकि fruit का प्रकार Fruit है, जो किसी भी SetFruit को पास करने के लिए मान्य प्रकार नहीं है। इसे गतिशील होना चाहिए क्योंकि ChangeType का स्थिर संकलन-समय प्रकार object है, जो किसी भी SetFruit के लिए भी मान्य प्रकार नहीं है।

वैकल्पिक रूप से, क्या होगा यदि आपने निर्णय को FruitPicture में धकेल दिया?

public interface Covariant {
    void SetCompatibleFruit(Fruit f);
}

public class FruitPicture<T> : Picture, Covariant where T : Fruit {
    T myFruit = null;

    public void SetCompatibleFruit(Fruit f) {
        if (f is T tf)
            this.myFruit = tf;
    }
}

फिर बस प्रत्येक Covariant picture को fruit सेट करने के लिए कहें, यदि वह कर सकता है:

foreach (var fruit in myFruits) {
    foreach (var picture in myPictures) {
        if (picture is Covariant cov)
            cov.SetCompatibleFruit(fruit);
    }
}
0
NetMage 22 अक्टूबर 2018, 23:39