সি # কি রিটার্ন টাইপের সমবায় সমর্থন করে?


88

আমি .NET ফ্রেমওয়ার্কের সাথে কাজ করছি এবং আমি সত্যিই আমার ওয়েবসাইটের সমস্ত ব্যবহার করে এমন একটি কাস্টম ধরণের পৃষ্ঠা তৈরি করতে সক্ষম হতে চাই। সমস্যাটি তখনই আসে যখন আমি একটি নিয়ন্ত্রণ থেকে পৃষ্ঠাটি অ্যাক্সেস করার চেষ্টা করছি। আমি ডিফল্ট পৃষ্ঠার পরিবর্তে আমার নির্দিষ্ট ধরণের পৃষ্ঠাটি ফিরিয়ে দিতে সক্ষম হতে চাই। এই কাজ করতে কোন উপায় আছে কি?

public class MyPage : Page
{
    // My own logic
}

public class MyControl : Control
{
    public MyPage Page { get; set; }
}

উত্তর:


175

আপডেট: এই উত্তরটি ২০১১ সালে লেখা হয়েছিল two আমি বরং অবাক। ঘোষণার জন্য https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/ এর নীচে দেখুন ; আমি নিশ্চিত বিশদ অনুসরণ করবে।


দেখে মনে হচ্ছে আপনি যা চান তা রিটার্ন টাইপের সম্প্রচার। সি # রিটার্ন টাইপের সম্প্রচারকে সমর্থন করে না।

রিটার্ন টাইপ কোভারিয়েন্স হ'ল যেখানে আপনি বেস ক্লাস পদ্ধতিটি ওভাররাইড করেন যা একটি সুনির্দিষ্ট প্রকারকে আরও নির্দিষ্ট প্রকারের সাথে প্রত্যাবর্তন করে:

abstract class Enclosure
{
    public abstract Animal Contents();
}
class Aquarium : Enclosure
{
    public override Fish Contents() { ... }
}

এটি নিরাপদ কারণ এনক্লোজারের মাধ্যমে সামগ্রীগুলির গ্রাহকরা একটি প্রাণী প্রত্যাশা করে এবং অ্যাকোয়ারিয়াম কেবল এই প্রয়োজনীয়তাটিই পূরণ করবে না, তবুও আরও কঠোর প্রতিশ্রুতি দেওয়ার প্রতিশ্রুতি দেয়: যে প্রাণীটি সর্বদা একটি মাছ।

C # তে এই ধরণের কোভেরিয়েন্স সমর্থিত নয় এবং এটি কখনও সমর্থিত হওয়ার সম্ভাবনা কম। এটি সিএলআর দ্বারা সমর্থিত নয়। (এটি সি ++ এর সাহায্যে এবং সিএলআর-তে সি ++ / সিএলআই বাস্তবায়ন দ্বারা সমর্থিত; এটি নীচের প্রস্তাবিত ধরণের যাদুকরী সহায়ক পদ্ধতি তৈরি করে তা করে))

(কিছু ভাষা আনুষ্ঠানিক প্যারামিটার ধরণের বৈপরীত্যকেও সমর্থন করে - আপনি যে পদ্ধতিতে কোনও প্রাণী গ্রহণ করেন এমন একটি পদ্ধতিতে একটি মাছ গ্রহণ করে এমন কোনও পদ্ধতিকে আপনি ওভাররাইড করতে পারেন Again আবারও চুক্তিটি সম্পন্ন হয়; বেস শ্রেণীর জন্য কোনও মাছ হ্যান্ডল করা এবং প্রাপ্ত হওয়া প্রয়োজন) শ্রেণি কেবল মাছ, তবে যে কোনও প্রাণীকে পরিচালনা করবে না বলে প্রতিশ্রুতি দেয় Similarly একইভাবে, সি # এবং সিএলআর আনুষ্ঠানিক প্যারামিটার ধরণের বিপরীতে সমর্থন করে না))

আপনি এই সীমাবদ্ধতার চারপাশে কাজ করতে পারেন এমন কিছু করা:

abstract class Enclosure
{
    protected abstract Animal GetContents();
    public Animal Contents() { return this.GetContents(); }
}
class Aquarium : Enclosure
{
    protected override Animal GetContents() { return this.Contents(); }
    public new Fish Contents() { ... }
}

এখন আপনি ভার্চুয়াল পদ্ধতিকে ওভাররাইড করার এবং কম্পাইল-টাইম টাইপের অ্যাকোয়ারিয়ামের কোনও কিছু ব্যবহার করার সময় শক্তিশালী টাইপিংয়ের উভয় সুবিধা পান।


4
পারফেক্ট! আমি ভুলে গিয়েছিলাম লুকিয়ে!
কাইল স্লেটেন 21

4
সর্বদা হিসাবে ভাল উত্তর। আমরা কিছুক্ষণের জন্য সেই উত্তরগুলি মিস করছি।
ধনঞ্জয়

4
রিটার্ন-কোভেরিয়েন্স এবং প্যারাম-কনট্রাভিয়ারেন্সকে সমর্থন না করার কোনও যুক্তি কি কোথাও পড়তে পাওয়া যায়?
porges

26
@ এরিকলিপার্ট সি # গ্রুপ হয়ে যাওয়ার কারণে আমি সবসময় "ব্যাকস্টেজ" সম্পর্কে আগ্রহী, তাই আমাকে কেবল জিজ্ঞাসা করতে হবে: রিটার্ন টাইপের গোপনীয়তা কি কখনও সি # এর জন্য বিবেচিত হয়েছিল এবং খুব কম আরওআই বলে মনে হয়েছিল? আমি সময় এবং বাগডেটের সীমাবদ্ধতাগুলি বুঝতে পারি, তবে আপনার "কখনও সমর্থনযোগ্য হওয়ার সম্ভাবনা" বিবৃতি থেকে মনে হচ্ছে ডিজাইনের দলটি ভাষায় এটি না করে দেবে। বেড়ার অপর প্রান্তে, জাভা জাভা 5 এ এই ভাষা বৈশিষ্ট্যটি প্রবর্তন করেছে, তাই আমি আশ্চর্য হয়েছি যে ভাষা নকশা প্রক্রিয়া পরিচালনা করে এমন বৃহত্তর, অত্যধিক নীতিমালার মধ্যে তফাত কী।
ক্রিশ্চিয়ান ডায়াকোনসকু

7
@ সাইরাল: সঠিক; এটি "মডারেট ইন্টারেস্ট" বাল্টির তালিকায় রয়েছে - এটি এখানে দীর্ঘকাল ধরে রয়েছে! এটি ঘটতে পারে, তবে আমি বেশ সন্দেহবাদী।
এরিক লিপার্ট

8

ইন্টারফেসের সাথে আমি স্পষ্টভাবে ইন্টারফেসটি প্রয়োগ করে এটিকে ঘিরেছিলাম:

public interface IFoo {
  IBar Bar { get; }
}
public class Foo : IFoo {
  Bar Bar { get; set; }
  IBar IFoo.Bar => Bar;
}

2

এটি MyControl অবজেক্টে রাখলে কাজ হবে:

 public new MyPage Page {get return (MyPage)Page; set;}'

আপনি সম্পত্তিটিকে ওভাররাইড করতে পারবেন না কারণ এটি ভিন্ন ধরণের রিটার্ন দেয় ... তবে আপনি এটি পুনরায় সংজ্ঞা দিতে পারেন।

এটি তুলনামূলকভাবে সহজ হওয়ায় আপনার এই উদাহরণে সমবায়ত্বের দরকার নেই। সমস্ত করছেন বেস বস্তু inheriting হয় Pageথেকে MyPage। এর পরিবর্তে যে কোনওটি Controlআপনি ফিরে আসতে চান এর সম্পত্তিটির নতুন সংজ্ঞা দিতে হবেMyPagePagePageControl


1

হ্যাঁ, এটি সমবায় সমর্থন করে, তবে এটি আপনি অর্জন করার চেষ্টা করছেন ঠিক তার উপর নির্ভর করে depends

আমি জিনিসগুলির জন্য জেনেরিকগুলিও প্রচুর পরিমাণে ব্যবহার করার প্রবণতা রাখি যার অর্থ হ'ল আপনি যখন এমন কিছু করেন:

class X<T> {
    T doSomething() {
    }

}

class Y : X<Y> {
    Y doSomethingElse() {
    }
}

var Y y = new Y();
y = y.doSomething().doSomethingElse();

এবং আপনার প্রকারগুলি "হারা" করবেন না।


1

এটি আসন্ন সি # 9.0 (। নেট 5) এর জন্য একটি বৈশিষ্ট্য যার মধ্যে আপনি এখনই একটি পূর্বরূপ সংস্করণ ডাউনলোড করতে পারেন ।

নিম্নলিখিত কোডটি এখন সফলভাবে বিল্ড করে (দেওয়া ছাড়াই error CS0508: 'Tiger.GetFood()': return type must be 'Food' to match overridden member 'Animal.GetFood()')

class Food { }
class Meat : Food { }

abstract class Animal {
    public abstract Food GetFood();
}

class Tiger : Animal {
    public override Meat GetFood() => default;
}

class Program {
    static void Main() => new Tiger();
}

0

আমি চেষ্টা করে দেখিনি, কিন্তু এই কাজ করে না?

YourPageType myPage = (YourPageType)yourControl.Page;

4
হ্যাঁ, এটা করে। আমি কেবল চেষ্টা করতে এবং পুরো জায়গা জুড়ে ingালাই এড়াতে চাই।
কাইল স্লেটেন 21

0

হ্যাঁ. এটি করার একাধিক উপায় রয়েছে এবং এটি কেবল একটি বিকল্প:

আপনি আপনার পৃষ্ঠাকে এমন কিছু কাস্টম ইন্টারফেস বাস্তবায়িত করতে পারেন যা "গেটকন্টেক্সট" বা কোনও কিছুর নাম প্রকাশ করে এবং এটি আপনার নির্দিষ্ট তথ্য ফেরত দেয়। তারপরে আপনার নিয়ন্ত্রণটি কেবল পৃষ্ঠার জন্য অনুরোধ করতে পারে এবং কাস্ট করতে পারে:

var myContextPage = this.Page as IMyContextGetter;

if(myContextPage != null)
   var myContext = myContextPage.GetContext();

তারপরে আপনি যে প্রসঙ্গটি চান তা ব্যবহার করতে পারেন।


0

প্যারেন্ট ট্রিটি চালিয়ে আপনি যে কোনও নিয়ন্ত্রণ থেকে আপনার পৃষ্ঠা অ্যাক্সেস করতে পারেন। এটাই

myParent = this;

while(myParent.parent != null)
  myParent = myParent.parent;

* সংকলন বা পরীক্ষা করেনি

অথবা বর্তমান প্রসঙ্গে পিতামাতাগুলি পান (আপনার সংস্করণের উপর নির্ভর করে)।


তারপরে আমি যা করতে চাই তা হ'ল: আমি নিয়ন্ত্রণে যে ফাংশনগুলি ব্যবহার করতে চাই তার সাথে একটি ইন্টারফেস তৈরি করি (উদাহরণস্বরূপ IHostingPage)

তারপরে আমি প্যারেন্ট পৃষ্ঠাটি 'আইহোস্টিংপেজ হোস্ট = (আইহোস্টিংপেজ) পিতা বা মাতা; এবং আমার নিয়ন্ত্রণ থেকে আমার প্রয়োজনীয় পৃষ্ঠায় ফাংশনটি কল করতে আমি প্রস্তুত।


0

আমি এটি এইভাবে করব:

class R {
    public int A { get; set; }
}

class R1: R {
    public int B { get; set; }
}

class A
{        
    public R X { get; set; }
}

class B : A 
{
    private R1 _x;
    public new R1 X { get => _x; set { ((A)this).X = value; _x = value; } }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.