সি # - স্পষ্টভাবে প্রকারের তালিকা <প্রোডাক্ট> কে তালিকায় <আইডি প্রোডাক্ট> রূপান্তর করতে পারে না


89

আমার সমস্ত ইন্টারফেস সংজ্ঞা সহ আমার একটি প্রকল্প রয়েছে: রিভ ওয়ার্কস
I ইন্টারফেসগুলি আমার এমন একটি প্রকল্প আছে যেখানে আমি কংক্রিটের প্রতিবিধানগুলি সংজ্ঞায়িত করি: রিভ ওয়ার্কস.ডিটিও

আমি এর আগে কয়েকশোবার এটি করেছি তবে কোনও কারণে আমি এখন এই ত্রুটিটি পাচ্ছি:

'সিস্টেম.কলেশনস.জেনারিক.লাইস্ট <রিভ ওয়ার্কস.ডিটিও.প্রডাক্ট>' তে 'সিস্টেম.কলেশনস.জেনারিক.লাইস্ট <রিভ ওয়ার্কস.ইনটারফেসস.ডাটা কনট্রাক্টস.আইডি প্রোডাক্ট>' প্রকারে স্পষ্টভাবে রূপান্তর করা যায় না '

ইন্টারফেস সংজ্ঞা (সংক্ষিপ্ত):

namespace RivWorks.Interfaces.DataContracts
{
    public interface IProduct
    {
        [XmlElement]
        [DataMember(Name = "ID", Order = 0)]
        Guid ProductID { get; set; }
        [XmlElement]
        [DataMember(Name = "altID", Order = 1)]
        long alternateProductID { get; set; }
        [XmlElement]
        [DataMember(Name = "CompanyId", Order = 2)]
        Guid CompanyId { get; set; }
        ...
    }
}

কংক্রিট বর্গ সংজ্ঞা (সংক্ষিপ্ত):

namespace RivWorks.DTO
{
    [DataContract(Name = "Product", Namespace = "http://rivworks.com/DataContracts/2009/01/15")]
    public class Product : IProduct
    {
        #region Constructors
        public Product() { }
        public Product(Guid ProductID)
        {
            Initialize(ProductID);
        }
        public Product(string SKU, Guid CompanyID)
        {
            using (RivEntities _dbRiv = new RivWorksStore(stores.RivConnString).NegotiationEntities())
            {
                model.Product rivProduct = _dbRiv.Product.Where(a => a.SKU == SKU && a.Company.CompanyId == CompanyID).FirstOrDefault();
                if (rivProduct != null)
                    Initialize(rivProduct.ProductId);
            }
        }
        #endregion

        #region Private Methods
        private void Initialize(Guid ProductID)
        {
            using (RivEntities _dbRiv = new RivWorksStore(stores.RivConnString).NegotiationEntities())
            {
                var localProduct = _dbRiv.Product.Include("Company").Where(a => a.ProductId == ProductID).FirstOrDefault();
                if (localProduct != null)
                {
                    var companyDetails = _dbRiv.vwCompanyDetails.Where(a => a.CompanyId == localProduct.Company.CompanyId).FirstOrDefault();
                    if (companyDetails != null)
                    {
                        if (localProduct.alternateProductID != null && localProduct.alternateProductID > 0)
                        {
                            using (FeedsEntities _dbFeed = new FeedStoreReadOnly(stores.FeedConnString).ReadOnlyEntities())
                            {
                                var feedProduct = _dbFeed.AutoWithImage.Where(a => a.ClientID == companyDetails.ClientID && a.AutoID == localProduct.alternateProductID).FirstOrDefault();
                                if (companyDetails.useZeroGspPath.Value || feedProduct.GuaranteedSalePrice > 0)     // kab: 2010.04.07 - new rules...
                                    PopulateProduct(feedProduct, localProduct, companyDetails);
                            }
                        }
                        else
                        {
                            if (companyDetails.useZeroGspPath.Value || localProduct.LowestPrice > 0)                // kab: 2010.04.07 - new rules...
                                PopulateProduct(localProduct, companyDetails);
                        }
                    }
                }
            }
        }
        private void PopulateProduct(RivWorks.Model.Entities.Product product, RivWorks.Model.Entities.vwCompanyDetails RivCompany)
        {
            this.ProductID = product.ProductId;
            if (product.alternateProductID != null)
                this.alternateProductID = product.alternateProductID.Value;
            this.BackgroundColor = product.BackgroundColor;
            ...
        }
        private void PopulateProduct(RivWorks.Model.Entities.AutoWithImage feedProduct, RivWorks.Model.Entities.Product rivProduct, RivWorks.Model.Entities.vwCompanyDetails RivCompany)
        {
            this.alternateProductID = feedProduct.AutoID;
            this.BackgroundColor = Helpers.Product.GetCorrectValue(RivCompany.defaultBackgroundColor, rivProduct.BackgroundColor);
            ...
        }
        #endregion

        #region IProduct Members
        public Guid ProductID { get; set; }
        public long alternateProductID { get; set; }
        public Guid CompanyId { get; set; }
        ...
        #endregion
    }
}

অন্য একটি ক্লাসে আমার রয়েছে:

using dto = RivWorks.DTO;
using contracts = RivWorks.Interfaces.DataContracts;
...
public static List<contracts.IProduct> Get(Guid companyID)
{
    List<contracts.IProduct> myList = new List<dto.Product>();
    ...

কোনও ধারণা কেন এমন হচ্ছে? (এবং আমি নিশ্চিত এটি তুচ্ছ সহজ কিছু!)

উত্তর:


114

হ্যাঁ এটি সি # তে একটি সমবায় সীমাবদ্ধতা। আপনি এক ধরণের তালিকা অন্য তালিকায় রূপান্তর করতে পারবেন না।

পরিবর্তে:

List<contracts.IProduct> myList = new List<dto.Product>();

আপনাকে এটি করতে হবে

List<contracts.IProduct> myList = new List<contracts.IProduct>();

myList.Add(new dto.Product());

এরিক লিপার্ট ব্যাখ্যা করেছেন যে তারা কেন এটিকে এটি প্রয়োগ করেছেন: http://blogs.msdn.com/ericlippert/archive/tags/Covariance+++ontontrolia/default.aspx

(এবং কেন এটি আইটেমের অ্যারে নিয়ে কাজ করার চেয়ে আলাদা)।


ড্যানিয়েল এবং কেভিন উভয়ই এর উত্তর দিয়েছেন, যদিও ভিন্ন ভিন্ন উপায়ে। ব্রাভো! বৈপরীত্য / covariance ন্যায্য ব্যাখ্যা। এটি প্রকৃতপক্ষে হয় বা হয় তবে উভয়ই নয়। .NET 4.0 ব্যবহার না করে আমার মন পুরোপুরি পিছলে গেল! ধন্যবাদ বন্ধুরা.
কীথ ব্যারো

39

আপনি এটা করতে পারবেন না। আপনি যদি একটি থাকে তাহলে List<IProduct>, আপনি লাগাতে পারেন কোনো IProduct এতে। সুতরাং আপনার যদি একটি Product2প্রয়োগ রয়েছে IProductতবে আপনি এটি তালিকায় রাখতে পারেন। তবে মূল তালিকাটি তৈরি করা হয়েছিল List<Product>, সুতরাং যে কেউ তালিকাটি ব্যবহার করছেন কেবলমাত্র টাইপের অবজেক্টগুলি আশা করবেনProduct না Product2তালিকায় যাবে।

.NET 4.0-এ, তারা ইন্টারফেসের জন্য সমবায়তা এবং বিপরীতে যুক্ত করেছে, যাতে আপনি রূপান্তর IEnumerable<Product>করতে পারেন IEnumerable<IProduct>। তবে এটি এখনও তালিকার পক্ষে কাজ করে না, যেহেতু তালিকার ইন্টারফেস আপনাকে উভয়কে "স্টাফ লাগাতে" এবং "স্টাফ আউট" করতে দেয়।


8
আইনিউমেবল ব্যবহার করতে সক্ষম হবার জন্য দুর্দান্ত টিপ
লি এন্লেস্টোন

আমি এখনও এই অংশটি দ্বারা কিছুটা বিভ্রান্ত হয়েছি:> সুতরাং যে কেউ তালিকার ব্যবহার করছেন কেবলমাত্র পণ্য ধরণের পণ্যগুলিই প্রত্যাশা করবে, তালিকায় প্রোডাক্ট 2 নয়। ব্যবহারকারী কেন এই ধারণাটি করবেন? আমি যদি তালিকা <আইডি প্রোডাক্ট> হিসাবে ঘোষিত কিছু ব্যবহার করছি তবে আমি আশা করব না যে কোনও একটি প্রয়োগ বা অন্যটিতে স্বয়ংক্রিয়ভাবে উপাদানগুলি হ্রাস করতে সক্ষম হবে। (এটি এমএসএফটি-র পছন্দ না করেই আমি পছন্দ করি তবে এটি সত্যই সম্ভব তবে আমি তাদের যুক্তি বোঝার চেষ্টা করতে চাই))
এলেনর হোলি

5

ঠিক একটি মন্তব্য হিসাবে: জেনারিক্সে কোভেরিয়েন্স এবং কনট্রাভারিয়েন্স সি # 4.0 তে যুক্ত হয়েছিল।


4
কিন্তু IN এবং OUT উভয় চ্যানেল রয়েছে এমন কনস্ট্রাক্টসে সমর্থিত নয়। তালিকা <T> এমন একটি নির্মাণ যাতে তারা বিপরীত / সমবায় সমর্থন করে না!
কিথ ব্যারো

হ্যাঁ, এটি কেবল তখনই কাজ করবে যদি একটি অনুমিত <কন্ট্রাক্টস.প্রযুক্তি>
ড্যানভিল

4

ঠিক আছে, আপনি এটি ব্যবহার করতে পারেন!

        class A {}
        class B : A {}
        ...
        List<B> b = new List<B>();
        ...
        List<A> a = new List<A>(b.ToArray());

এখন, সরাসরি সমাধান দিতে,

using dto = RivWorks.DTO;
using contracts = RivWorks.Interfaces.DataContracts;
...
public static List<contracts.IProduct> Get(Guid companyID) {
    List<dto.Product> prodList = new List<dto.Product>();
    ...
    return new List<contracts.IProduct>(prodList.ToArray());
}

2

এটি কীভাবে করা যায় এটি একটি সামান্য উদাহরণ।

    public void CreateTallPeople()
    {
        var tallPeopleList = new List<IPerson>
        {
            new TallPerson {Height = 210, Name = "Stevo"},
            new TallPerson {Height = 211, Name = "Johno"},
        };
        InteratePeople(tallPeopleList);
    }

    public void InteratePeople(List<IPerson> people)
    {
        foreach (var person in people)
        {
            Console.WriteLine($"{person.Name} is {person.Height}cm tall.  ");
        }
    }

-3

পরিবর্তে এটি চেষ্টা করুন:

List<contracts.IProduct> myList = new List<contracts.IProduct>((new List<dto.Product>()).Cast<contracts.IProduct>());

7
গুরুত্ব সহকারে? আপনি কি জানেন যে এমনকি এর মানে কি?
নিক্স
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.