সি # জেনেরিকের অকার্যকর?


94

আমার একটি জেনেরিক পদ্ধতি রয়েছে যা একটি অনুরোধ নেয় এবং প্রতিক্রিয়া সরবরাহ করে।

public Tres DoSomething<Tres, Treq>(Tres response, Treq request)
{/*stuff*/}

তবে আমি সবসময় আমার অনুরোধের জন্য প্রতিক্রিয়া চাই না এবং প্রতিক্রিয়া পেতে আমি সর্বদা অনুরোধের ডেটা ফিড করতে চাই না। আমিও চাই না যে ছোটখাটো পরিবর্তনগুলি করার জন্য তাদের সম্পূর্ণ পদ্ধতিগুলিকে কপি এবং পেস্ট করতে হবে। আমি যা চাই তা হ'ল এটি করতে সক্ষম হোন:

public Tre DoSomething<Tres>(Tres response)
{
    return DoSomething<Tres, void>(response, null);
}

এটি কি কোনও উপায়ে সম্ভব? দেখে মনে হচ্ছে বিশেষভাবে শূন্যতা ব্যবহার করা কার্যকর হয় না, তবে আমি প্রত্যাশা করছি যে কিছু মিল রয়েছে find


4
কেবলমাত্র সিস্টেম.অবজেক্টটি কেন ব্যবহার করবেন না এবং ডসোমথিং-এ একটি নাল চেক করবেন (ট্রেসের প্রতিক্রিয়া, ট্রেইকের অনুরোধ)?
জেমস

মনে রাখবেন যে আপনাকে ফেরতের মানটি ব্যবহার করতে হবে। আপনি প্রক্রিয়া মত ফাংশন কল করতে পারেন। DoSomething(x);পরিবর্তেy = DoSomething(x);
অলিভিয়ার জ্যাকট-ডেস্কোম্বেস

4
আমার মনে হয় আপনি বলতেন, বোঝানো "মনে রাখবেন আপনি না না ফেরত মান ব্যবহার করতে হবে।" @ OlivierJacot-Descombes
zanedp

উত্তর:


98

আপনি ব্যবহার করতে পারবেন না void, তবে আপনি ব্যবহার করতে পারেন object: এটি কিছুটা অসুবিধা কারণ আপনার voidকাজগুলি ফাংশনগুলির ফিরতে nullহবে তবে এটি যদি আপনার কোডটি একীভূত করে, তবে এটির মূল্য দিতে হবে একটি ছোট দাম।

voidরিটার্নের ধরন হিসাবে ব্যবহারের এই অক্ষমতা কমপক্ষে আংশিকভাবে জেনেরিক প্রতিনিধিদের Func<...>এবং Action<...>পরিবারের মধ্যে বিভক্ত হওয়ার জন্য দায়ী : যদি ফিরে আসা সম্ভব হত void, তবে সমস্ত কিছু Action<X,Y,Z>সরল হয়ে উঠত Func<X,Y,Z,void>। দুর্ভাগ্যক্রমে, এটি সম্ভব নয়।


48
(কৌতুক) এবং তিনি এখনও voidসেই বাতিল-পদ্ধতিগুলি থেকে ফিরে আসতে পারেন return System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof(void));। যদিও এটি একটি বক্সযুক্ত শূন্যতা হবে।
জেপ্পে স্টিগ নীলসন

4
যেহেতু সি # আরও কার্যকরী প্রোগ্রামিং বৈশিষ্ট্যগুলিকে সমর্থন করে, আপনি ইউনিটটি দেখে নিতে পারেন যা voidএফপিতে প্রতিনিধিত্ব করে। এবং এটি ব্যবহার করার ভাল কারণ রয়েছে। এফ # তে, এখনও। নেট, আমাদের unitবিল্ট-ইন রয়েছে।
জো

88

না, দুর্ভাগ্যবশত না. যদি void"রিয়েল" টাইপ হয় (যেমন unitF # তে , উদাহরণস্বরূপ) জীবন অনেক উপায়ে সহজ হত। বিশেষ করে, আমরা উভয় প্রয়োজন হত না Func<T>এবং Action<T>পরিবার - শুধু হতে চাই Func<void>পরিবর্তে Action, Func<T, void>পরিবর্তে Action<T>ইত্যাদি

এটি অ্যাসিঙ্ককে আরও সহজ করে তুলবে - অ-জেনেরিক Taskপ্রকারের কোনও দরকার নেই - আমাদের কেবল দরকার Task<void>

দুর্ভাগ্যক্রমে, সি # বা .NET টাইপ সিস্টেমগুলি সেভাবে কাজ করে না ...


4
Unfortunately, that's not the way the C# or .NET type systems work...আপনি আমাকে আশাবাদী করে তুলছিলেন যে সম্ভবত জিনিসগুলি শেষ পর্যন্ত এর মতো কাজ করতে পারে। আপনার শেষ পয়েন্টটির অর্থ হল যে আমরা কখনও জিনিসগুলি সেভাবে কাজ করি না?
ডেভ কাজিনো

4
@ সাহুয়াগিন: আমি সন্দেহ করি না - এই মুহুর্তে এটি বেশ বড় পরিবর্তন হবে।
জন স্কিটি

4
@ ইস্তানিয়াস: না, এটি ভুল কোডের দিকে নিয়ে যাওয়ার মতো কিছু অসুবিধাগুলি বেশি।
জন স্কিটি

4
"শূন্য" প্রতিনিধিত্ব করার জন্য খালি মূল্য প্রকারের তুলনায় ইউনিট রেফারেন্স টাইপ থাকার কি সুবিধা আছে? খালি মূল্য প্রকারটি আমার পক্ষে আরও উপযুক্ত বলে মনে হচ্ছে, এটির কোনও মূল্য নেই এবং কোনও স্থান নেয় না। আমি অবাক হয়েছি কেন এইভাবে শূন্যতা প্রয়োগ করা হয়নি। প্যাকিং বা স্ট্যাক থেকে পপিংয়ের কোনও পার্থক্য নেই (নেটিভ কোডের কথা বলা, আইএল এ এটি আলাদা হতে পারে)।
ওন্দ্রেজ পেট্রজিলকা

4
@ ওন্দ্রেজ: আমি আগে জিনিসগুলির জন্য একটি খালি কাঠামো ব্যবহার করার চেষ্টা করেছি এবং এটি সিএলআর-এ খালি না হয়ে শেষ হয়ে যায় ... অবশ্যই এটি বিশেষ ক্ষেত্রে হতে পারে। এর বাইরে, আমি জানি না আমি কোনটি প্রস্তাব করব; আমি এটি সম্পর্কে খুব ভেবে দেখিনি।
জন স্কিটি

27

আপনি যা করতে পারেন তা এখানে। @ জনসকিট যেমন বলেছিলেন যে সি # তে কোনও ইউনিটের প্রকার নেই, তাই নিজেই তৈরি করুন!

public sealed class ThankYou {
   private ThankYou() { }
   private readonly static ThankYou bye = new ThankYou();
   public static ThankYou Bye { get { return bye; } }
}

এখন আপনি সর্বদা এর Func<..., ThankYou>পরিবর্তে ব্যবহার করতে পারেনAction<...>

public ThankYou MethodWithNoResult() {
   /* do things */
   return ThankYou.Bye;
}

বা ইতিমধ্যে আরএক্স দল দ্বারা তৈরি কিছু ব্যবহার করুন: http://msdn.microsoft.com/en-us/library/system.reactive.unit%28v=VS.103%29.aspx


System.Reactive.Unit একটি ভাল পরামর্শ। নভেম্বর ২০১ of পর্যন্ত, আপনি যতটা সম্ভব প্রতিক্রিয়াশীল কাঠামোর একটি ছোট অংশ পেতে আগ্রহী, কারণ আপনি ইউনিট শ্রেণি ব্যতীত অন্য কিছু ব্যবহার করছেন না, নুগেট প্যাকেজ ম্যানেজার ব্যবহার করুনInstall-Package System.Reactive.Core
ড্যানিমিস্টার

6
আপনাকে "কেটিএইচএক্স" এর পুনঃনাম দিন, এবং এটি একটি বিজয়ী। ^ _ ^Kthx.Bye;
লেকসএইচ

কেবলমাত্র আমি কিছু মিস করছি না তা খতিয়ে দেখার জন্য .. বাই বাইর এখানে সরাসরি অ্যাক্সেসের চেয়ে উল্লেখযোগ্য কিছু যুক্ত করে না?
অ্যান্ড্রু

4
@ অ্যান্ড্রুয়ের জন্য আপনাকে বাই বাইকের দরকার নেই, যদি না আপনি সি # কোডিংয়ের চেতনা অনুসরণ করতে চান, যা আপনাকে খালি ক্ষেতগুলি উন্মোচিত করবেন না বলে মন্তব্য করে
ট্রিডেন্ট ডি'গাও

16

Objectঅন্যরা যেভাবে পরামর্শ দিয়েছে আপনি কেবল তা ব্যবহার করতে পারেন । বা Int32যা আমি কিছু ব্যবহার দেখেছি। ব্যবহার Int32প্রবর্তন একটি "ডামি" নম্বর (ব্যবহার 0), কিন্তু অন্তত আপনি একটি মধ্যে কোনো বড় এবং বহিরাগত বস্তু দূরে থাকতে পারে না Int32রেফারেন্স (structs মধ্যে সিল করা হয়)।

আপনি নিজের "অকার্যকর" প্রকারের লিখতেও পারেন:

public sealed class MyVoid
{
  MyVoid()
  {
    throw new InvalidOperationException("Don't instantiate MyVoid.");
  }
}

MyVoidতথ্যসূত্র অনুমোদিত (এটি একটি স্ট্যাটিক শ্রেণি নয়) তবে কেবল তা হতে পারে null। উদাহরণস্বরূপ কনস্ট্রাক্টরটি ব্যক্তিগত (এবং যদি কেউ প্রতিচ্ছবিটির মাধ্যমে এই বেসরকারী নির্মাণকারীকে কল করতে চেষ্টা করেন তবে একটি ব্যতিক্রম তাদের দিকে নিক্ষেপ করা হবে)।


যেহেতু মান টিপলস চালু হয়েছিল (2017,। নেট 4.7), সুতরাং এ জাতীয় পরিবর্তে স্ট্রাক্টValueTuple (0-টিপল, নন-জেনেরিক বৈকল্পিক) ব্যবহার করা স্বাভাবিক MyVoid। এর উদাহরণটিতে ToString()একটিটি ফিরে আসে "()", সুতরাং এটি শূন্য-টিপলের মতো দেখায়। সি # এর বর্তমান সংস্করণ হিসাবে, ()উদাহরণস্বরূপ আপনি কোডটিতে টোকেন ব্যবহার করতে পারবেন না । পরিবর্তে আপনি ব্যবহার করতে পারেন default(ValueTuple)বা কেবল default(যখন প্রসঙ্গটি থেকে প্রকারটি অনুমান করা যায়)।


4
এর অন্য নাম হ'ল নাল অবজেক্ট প্যাটার্ন (ডিজাইনের প্যাটার্ন)।
আলেফাইস

@ আলেফাইস এই ধারণাটি নাল বস্তুর ধরণ থেকে কিছুটা আলাদা। এখানে, বিন্দুটি কেবল একটি জেনেরিকের সাথে আমরা ব্যবহার করতে পারি এমন কিছু ধরণের to নাল অবজেক্ট প্যাটার্ন সহ লক্ষ্যটি হ'ল কোনও পদ্ধতি রচনা এড়ানো যা কোনও বিশেষ ক্ষেত্রে নির্দেশিত করতে নাল ফেরায় এবং পরিবর্তে যথাযথ ডিফল্ট আচরণের সাথে একটি আসল বস্তুটি ফিরিয়ে দেয়।
অ্যান্ড্রু পামার

8

আমি উপরে আলেক্সি বাইকভের ধারণাটি পছন্দ করি তবে এটি কিছুটা সহজ করা যায়

public sealed class Nothing {
    public static Nothing AtAll { get { return null; } }
}

যেহেতু আমি কোনও আপত্তিজনক কারণ দেখতে পাচ্ছি না কেন কিছুই না tআল সব কেবল শূন্য করতে পারেনি

একই ধারণা (বা জেপ্প স্টিগ নীলসনের একটি) টাইপযুক্ত শ্রেণীর সাথে ব্যবহারের জন্যও দুর্দান্ত।

উদাহরণস্বরূপ, যদি টাইপটি কোনও পদ্ধতিতে আর্গুমেন্ট হিসাবে কোনও পদ্ধতি / ফাংশনটিতে আর্গুমেন্ট বর্ণনা করতে ব্যবহৃত হয় এবং এটি নিজে কোনও যুক্তি গ্রহণ করে না।

(আপনাকে এখনও ডামি মোড়ক তৈরি করতে হবে বা একটি alচ্ছিক "কিছুই না" দেওয়ার অনুমতি দিতে হবে। তবে ক্লাসের ব্যবহারটি মাই ক্লাস << কিছুই>> এর সাথে দেখতে সুন্দর দেখাচ্ছে)

void myProcWithNoArguments(Nothing Dummy){
     myProcWithNoArguments(){
}

বা

void myProcWithNoArguments(Nothing Dummy=null){
    ...
}

4
মানটির nullঅনুপস্থিত বা অনুপস্থিত থাকার অর্থ রয়েছে object। একটির জন্য কেবল একটি মান থাকা এটি Nothingঅন্য কোনও কিছুর মতো দেখায় না।
লেক্সএইচ

এটি একটি ভাল ধারণা, তবে আমি @LaxieHankins এর সাথে একমত। আমি মনে করি "কোনও কিছুই নয়" Nothingএকটি ব্যক্তিগত স্ট্যাটিক ক্ষেত্রে সংরক্ষণ করা ক্লাস এবং একটি বেসরকারী নির্মাণকারী যুক্ত করার একটি অনন্য উদাহরণ হতে ভাল হবে । নাল এখনও সম্ভব তা সত্যই বিরক্তিকর, তবে এটি সমাধান হবে আশা করি C # 8 দিয়ে
र्क ওল

একাডেমিকভাবে আমি পার্থক্যটি বুঝতে পারি, তবে এটি খুব বিশেষ ক্ষেত্রে হবে যেখানে পার্থক্যটি গুরুত্বপূর্ণ। (জেনেরিক নালামযোগ্য টাইপের কোনও ফাংশনটি কল্পনা করুন, যেখানে "নাল" এর প্রত্যাবর্তনটি বিশেষ চিহ্নিতকারী হিসাবে ব্যবহৃত হয়, যেমন
কোনওরকম

4

voidযদিও কোনও প্রকার, কেবল কোনও পদ্ধতির রিটার্ন টাইপ হিসাবে বৈধ।

এর সীমাবদ্ধতার আশেপাশে কোনও উপায় নেই void


1

আমি বর্তমানে যা করছি তা হ'ল প্রাইভেট কনস্ট্রাক্টর সহ কাস্টম সিলড টাইপগুলি তৈরি করা। এটি সি-টর্মে ব্যতিক্রম ছোঁড়ার চেয়ে ভাল কারণ পরিস্থিতিটি ভুল হিসাবে খুঁজে বের করতে আপনাকে রানটাইম পর্যন্ত পেতে হবে না। স্থির উদাহরণটি ফেরত দেওয়ার চেয়ে সূক্ষ্মভাবে ভাল কারণ আপনাকে একবারেও বরাদ্দ দিতে হবে না। স্থির নাল ফিরে আসার চেয়ে এটি সূক্ষ্মভাবে ভাল কারণ এটি কল দিকে কম ভার্জোজ। কলকারী কেবলমাত্র যা করতে পারে তা হ'ল শূন্য করা।

public sealed class Void {
    private Void() { }
}

public sealed class None {
    private None() { }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.