আমি .NET এ স্ট্রাক্টের জন্য ডিফল্ট কনস্ট্রাক্টরকে কেন সংজ্ঞায়িত করতে পারি না?


261

.NET- এ, কোনও মান ধরণের (সি # struct) কোনও প্যারামিটার ছাড়া কোনও কনস্ট্রাক্টর থাকতে পারে না। এই পোস্ট অনুযায়ী এটি সিএলআই স্পেসিফিকেশন দ্বারা বাধ্যতামূলক হয়। যা ঘটে তা প্রতিটি মান-প্রকারের জন্য একটি ডিফল্ট কনস্ট্রাক্টর তৈরি করা হয় (সংকলক দ্বারা?) যা সমস্ত সদস্যকে শূন্য (বা null) থেকে আরম্ভ করে ।

কেন এমন ডিফল্ট কনস্ট্রাক্টর সংজ্ঞায়িত করার অনুমতি দেওয়া হয় না?

একটি তুচ্ছ ব্যবহার যুক্তিসঙ্গত সংখ্যার জন্য:

public struct Rational {
    private long numerator;
    private long denominator;

    public Rational(long num, long denom)
    { /* Todo: Find GCD etc. */ }

    public Rational(long num)
    {
        numerator = num;
        denominator = 1;
    }

    public Rational() // This is not allowed
    {
        numerator = 0;
        denominator = 1;
    }
}

সি # এর বর্তমান সংস্করণ ব্যবহার করে, একটি ডিফল্ট যুক্তিযুক্ত 0/0যা এতটা দুর্দান্ত নয়।

PS : ডিফল্ট প্যারামিটারগুলি কি এটি সি # 4.0 এর সমাধান করতে সহায়তা করবে বা সিএলআর-সংজ্ঞায়িত ডিফল্ট কনস্ট্রাক্টর বলা হবে?


জোন স্কিকেট উত্তর দিয়েছে:

আপনার উদাহরণটি ব্যবহার করতে, যখন কেউ এমনটি ঘটে তখন আপনি কী হতে চান:

 Rational[] fractions = new Rational[1000];

এটি কি আপনার নির্মাণকারীর মাধ্যমে 1000 বার চালানো উচিত?

অবশ্যই এটি হওয়া উচিত, এজন্য আমি প্রথম স্থানে ডিফল্ট কনস্ট্রাক্টর লিখেছিলাম। যখন কোনও স্পষ্টত ডিফল্ট নির্মাতাকে সংজ্ঞায়িত না করা হয় তখন সিএলআরটিকে ডিফল্ট শূণ্য নির্মাণকারী ব্যবহার করা উচিত ; এইভাবে আপনি কেবল যা ব্যবহার করেন তার জন্য অর্থ প্রদান করুন। তারপরে আমি যদি 1000 নন-ডিফল্ট Rationalগুলি (এবং 1000 নির্মাণগুলি অপ্টিমাইজ করতে চাই) এর ধারক চাই তবে আমি List<Rational>অ্যারের পরিবর্তে একটি ব্যবহার করব ।

এই কারণে, মনে মনে, কোনও ডিফল্ট নির্মাতার সংজ্ঞা রোধ করতে যথেষ্ট শক্তিশালী নয়।


3
+1 এর একবার একই সমস্যা হয়েছিল, অবশেষে স্ট্রাক্টটিকে ক্লাসে রূপান্তরিত করে।
ডার্ক ভোলমার

4
সি # 4 এ ডিফল্ট প্যারামিটারগুলি সাহায্য করতে পারে না কারণ Rational()এটি পরামিতি বিহীন কর্টরের চেয়ে ডাকে Rational(long num=0, long denom=1)
ল্যাটেক্স

6
মনে রাখবেন যে সি # 6.0 এ ভিজ্যুয়াল স্টুডিও 2015 এর সাথে আসে এটি স্ট্রোকগুলির জন্য শূন্য-প্যারামিটার উদাহরণ কন্সট্রাক্টর লেখার মঞ্জুরিপ্রাপ্ত। সুতরাং new Rational()এটি নির্মাণকারীর কাছে উপস্থিত থাকলে এটি উপস্থিত থাকলে এটি উপস্থিত না থাকলে new Rational()সমতুল্য হবে default(Rational)। আপনি default(Rational)যখন আপনার কাঠামোর "শূন্য মান" চান (যা আপনার প্রস্তাবিত নকশার সাথে একটি "খারাপ" সংখ্যা Rational) চান তখন যে কোনও ক্ষেত্রে আপনাকে সিনট্যাক্সটি ব্যবহার করতে উত্সাহিত করা হবে । একটি মান টাইপ জন্য ডিফল্ট মান Tসর্বদা default(T)। সুতরাং new Rational[1000]স্ট্রাক্ট কনস্ট্রাক্টরদের কখনই ডাকতে হবে না।
জেপ্প স্টিগ নীলসন

6
এই নির্দিষ্ট সমস্যা সমাধানের জন্য আপনি denominator - 1স্ট্রাক্টের ভিতরে সঞ্চয় করতে পারেন , যাতে ডিফল্ট মান 0/1 হয়ে যায়
মিনিবিল

3
Then if I want a container of 1000 non-default Rationals (and want to optimize away the 1000 constructions) I will use a List<Rational> rather than an array.আপনি কেন অ্যারের কাছ থেকে স্ট্রাক্টের জন্য একটি তালিকাতে অন্য নির্মাণকারীকে অনুরোধ করবেন?
mjwills

উত্তর:


197

দ্রষ্টব্য: নীচের উত্তরটি সি # 6 এর অনেক আগে লেখা হয়েছিল, যা স্ট্রাইকগুলিতে প্যারামিটারলেস কনস্ট্রাক্টর ঘোষণার সক্ষমতা প্রবর্তনের পরিকল্পনা করছে - তবে তাদের এখনও সব পরিস্থিতিতে ডাকা হবে না (যেমন অ্যারে তৈরির জন্য) (শেষ পর্যন্ত এই বৈশিষ্ট্যটি সি # 6 এ যুক্ত করা হয়নি )।


সম্পাদনা: সিএলআর-তে গ্রাওনওল্ফের অন্তর্দৃষ্টির কারণে আমি নীচের উত্তরটি সম্পাদনা করেছি।

সিএলআর মান ধরণেরগুলিকে প্যারামিটারলেস কনস্ট্রাক্টর রাখতে দেয় তবে সি # হয় না doesn't আমি বিশ্বাস করি এটি এর কারণ এটি এমন একটি প্রত্যাশা প্রবর্তন করবে যা নির্মাণকারীকে ডাকা হবে না যখন এটি হবে না। উদাহরণস্বরূপ, এটি বিবেচনা করুন:

MyStruct[] foo = new MyStruct[1000];

সিএলআর কেবল যথাযথ মেমরির বরাদ্দ করে এবং এটির সমস্ত কাজ শূন্য করে খুব দক্ষতার সাথে এটি করতে সক্ষম। যদি এটি 1000 বার মাইস্ট্রাক্ট কনস্ট্রাক্টর চালাতে হয় তবে এটি অনেক কম দক্ষ হবে। (আসলে, এটি হয় না - যদি আপনার কাছে প্যারামিটারলেস কনস্ট্রাক্টর থাকে তবে আপনি অ্যারে তৈরি করার সময়, বা যখন আপনার অবিশ্বাস্য উদাহরণ ভেরিয়েবল থাকে এটি চালানো হয় না))

সি # এর বেসিক নিয়মটি হ'ল "যে কোনও ধরণের ডিফল্ট মান কোনও প্রারম্ভিকতার উপর নির্ভর করতে পারে না"। এখন তারা প্যারামিটারলেস কনস্ট্রাক্টরকে সংজ্ঞায়িত করার অনুমতি দিতে পারত , তবে তার পরে প্রয়োজন হয়নি যে সমস্ত ক্ষেত্রেই কনস্ট্রাক্টর মৃত্যুদন্ড কার্যকর করা উচিত - তবে এটি আরও বিভ্রান্তির কারণ হতে পারে। (বা কমপক্ষে, তাই আমি বিশ্বাস করি যুক্তিটি যায়))

সম্পাদনা: আপনার উদাহরণটি ব্যবহার করার জন্য, যখন কেউ এমনটি করেছিল তখন আপনি কী হতে চান:

Rational[] fractions = new Rational[1000];

এটি কি আপনার নির্মাণকারীর মাধ্যমে 1000 বার চালানো উচিত?

  • যদি তা না হয় তবে আমরা 1000 টি অবৈধ যুক্তি দিয়ে শেষ করি
  • যদি এটি হয়, তবে আমরা প্রকৃত মূল্যবোধের সাথে অ্যারে পূরণ করতে চাইলে আমরা সম্ভাব্য পরিমাণের কাজের অপচয় করব।

সম্পাদনা: (প্রশ্নের আরও কিছুটা উত্তর দিচ্ছি) পরামিতিবিহীন নির্মাণকারী সংকলক তৈরি করেননি। যদিও এটি সক্রিয় আউট এটা - মূল্য ধরনের কনস্ট্রাকটর আছে যতদূর CLR সংশ্লিষ্ট হয় না করতে পারেন যদি আপনি এটি বিশ্বের সেরা লিখুন। আপনি যখন new Guid()সি # তে " " লিখেন যা কোনও সাধারণ কনস্ট্রাক্টরকে কল করলে আপনি কী পান তার জন্য বিভিন্ন আইএল নির্গত হয়। সেই দিকটি সম্পর্কে এই আরও প্রশ্নটি দেখুন ।

আমার সন্দেহ হয় যে প্যারামিটারলেস কনস্ট্রাক্টরগুলির সাথে ফ্রেমওয়ার্কে কোনও মান ধরণের নেই। নিঃসন্দেহে এনডিপেন্ডই আমাকে বলতে পারত যদি আমি এটি যথেষ্ট সুন্দরভাবে জিজ্ঞাসা করি ... সি # এটি নিষিদ্ধ করার বিষয়টি আমার পক্ষে সম্ভবত এটি খারাপ ধারণা বলে ভাবা যথেষ্ট বড় ইঙ্গিত।


9
সংক্ষিপ্ত ব্যাখ্যা: সি ++ তে স্ট্রাক্ট এবং ক্লাস একই মুদ্রার মাত্র দুটি দিক ছিল। একমাত্র আসল পার্থক্যটি হ'ল একটি ডিফল্টরূপে সর্বজনীন এবং অন্যটি ব্যক্তিগত। নেট। এ, কাঠামো এবং শ্রেণীর মধ্যে অনেক বেশি পার্থক্য রয়েছে এবং এটি বোঝা গুরুত্বপূর্ণ।
জোয়েল কোহোর্ন 14

38
@ জোয়েল: এটি এই নির্দিষ্ট সীমাবদ্ধতার সত্যই ব্যাখ্যা করে না, তাই না?
জন স্কিটি

6
সিএলআর মান ধরণেরগুলিকে প্যারামিটারলেস কনস্ট্রাক্টর রাখার অনুমতি দেয়। এবং হ্যাঁ, এটি এটি অ্যারেতে প্রতিটি উপাদানগুলির জন্য চালাবে। সি # এটি একটি খারাপ ধারণা বলে মনে করে এবং এটির অনুমতি দেয় না তবে আপনি একটি নেট নেট ভাষা লিখতে পারেন।
জোনাথন অ্যালেন

2
দুঃখিত, আমি নিম্নলিখিতটি নিয়ে কিছুটা বিভ্রান্ত। না Rational[] fractions = new Rational[1000];আরো কাজ লোড অপচয় যদি Rationalএকটি বর্গ একটি struct পরিবর্তে কি? যদি তাই হয় তবে ক্লাসগুলির ডিফল্ট কর্টর থাকবে কেন?
আমার বগলে চুমু

5
@ ফিফাআর্থার্থকপ २०१৪: "কাজের প্রচুর অপচয় নষ্ট" দ্বারা আপনি কী বোঝাতে চাইছেন সে সম্পর্কে আপনাকে আরও নির্দিষ্ট হতে হবে। কিন্তু যখন কোনও উপায়ে এটি কনস্ট্রাক্টরকে 1000 বার কল করবে না। যদি Rationalশ্রেণি হয় তবে আপনার 1000 টি নাল রেফারেন্সের সমাপ্তি হবে।
জন স্কিটি

48

একটি কাঠামো একটি মান প্রকার এবং কোনও মান টাইপের অবশ্যই এটি ঘোষণার সাথে সাথে একটি ডিফল্ট মান থাকতে হবে।

MyClass m;
MyStruct m2;

যদি আপনি উভয় ক্ষেত্রে তাত্ক্ষণিক না করে উপরে দুটি ক্ষেত্র হিসাবে ঘোষণা করেন তবে ডিবাগারটি ভাঙ্গুন, mনাল m2হবে তবে তা হবে না। এটি প্রদত্ত, একটি প্যারামিটারলেস কনস্ট্রাক্টর কোনও অর্থ বোধ করবে না, বাস্তবে কোনও স্ট্রাক্টের যে কোনও কনস্ট্রাক্টর মানগুলি নির্ধারণ করে, জিনিসটি ইতিমধ্যে এটি ঘোষণা করেই বিদ্যমান exists প্রকৃতপক্ষে উপরের উদাহরণটিতে এম 2 বেশ সুখের সাথে ব্যবহার করা যেতে পারে এবং এর পদ্ধতিগুলি যদি কোনও হয় তবে এটির ক্ষেত্র এবং সম্পত্তি হেরফের করা যেতে পারে!


3
কেউ আপনাকে কেন ভোট দিয়েছে বলে নিশ্চিত নয়। আপনি এখানে সবচেয়ে সঠিক উত্তর হিসাবে প্রদর্শিত হবে।
পাইপজাইক

12
সি ++ এর আচরণটি হ'ল যদি কোনও ধরণের ডিফল্ট কনস্ট্রাক্টর থাকে তবে এটি ব্যবহার করা হয় যখন এই ধরণের অবজেক্টটি সুস্পষ্ট কনস্ট্রাক্টর ছাড়াই তৈরি করা হয়। এটি সি # তে ডিফল্ট কনস্ট্রাক্টরের সাথে এম 2 শুরু করার জন্য ব্যবহার করা যেতে পারে যার কারণে এই উত্তরটি সহায়ক নয়।
মোটি

3
সিলেস্টার: ঘোষিত হওয়ার পরে যদি আপনি নিজের কন্সট্রাক্টরকে কল করতে স্ট্রাইকগুলি না চান, তবে এই জাতীয় ডিফল্ট কনস্ট্রাক্টর সংজ্ঞায়িত করবেন না! :) এটি
মট্টির

8
@Tarik। আমি একমত না. বিপরীতে, একটি প্যারামিটারলেস কনস্ট্রাক্টর পুরো বোধ করতে পারে: যদি আমি একটি "ম্যাট্রিক্স" স্ট্রাক্ট তৈরি করতে চাই তবে সর্বদা একটি ডিফল্ট মান হিসাবে একটি পরিচয় ম্যাট্রিক থাকে তবে আপনি কীভাবে এটি অন্য উপায়ে করতে পারবেন?
এলো

1
আমি নিশ্চিত নই যে আমি "সত্যই এম 2 বেশ আনন্দের সাথে ব্যবহার করতে পারলাম .." এর সাথে আমি সম্পূর্ণরূপে একমত । এটি পূর্ববর্তী সি # তে সত্য হতে পারে তবে এটি কোনও স্ট্রাক্ট ঘোষণা করতে সংকলক ত্রুটি, newএটি নয় , এর সদস্যদের ব্যবহারের চেষ্টা করুন
Caius Jard

18

যদিও সিএলআর এটির অনুমতি দেয়, সি # স্ট্র্টকে ডিফল্ট প্যারামিটার-কম কমস্ট্রাক্টর রাখার অনুমতি দেয় না। কারণটি হ'ল, কোনও মান ধরণের জন্য, সংকলকরা ডিফল্টরূপে ডিফল্ট কনস্ট্রাক্টর জেনারেট করে না বা ডিফল্ট কনস্ট্রাক্টরকে কল দেয় না। সুতরাং, এমনকি যদি আপনি কোনও ডিফল্ট কনস্ট্রাক্টর সংজ্ঞায়িত করার ঘটনা ঘটে থাকে তবে এটি ডাকা হবে না এবং এটি আপনাকে বিভ্রান্ত করবে।

এই জাতীয় সমস্যা এড়াতে, সি # সংকলক ব্যবহারকারীর দ্বারা ডিফল্ট নির্মাতার সংজ্ঞাটিকে অস্বীকার করে। এবং এটি কোনও ডিফল্ট কনস্ট্রাক্টর জেনারেট না করার কারণে আপনি ক্ষেত্রগুলি সংজ্ঞায়িত করার সময় আরম্ভ করতে পারবেন না।

বা এর বড় কারণ হ'ল একটি কাঠামো একটি মান ধরণের এবং মান প্রকারগুলি একটি ডিফল্ট মান দ্বারা আরম্ভ করা হয় এবং কনস্ট্রাক্টরটি আরম্ভের জন্য ব্যবহৃত হয়।

newকীওয়ার্ড দিয়ে আপনাকে আপনার স্ট্রাক্ট ইনস্ট্যান্ট করতে হবে না । পরিবর্তে এটি একটি ইন্টের মতো কাজ করে; আপনি সরাসরি এটি অ্যাক্সেস করতে পারেন।

স্ট্রাক্টগুলিতে সুস্পষ্ট প্যারামিটারলেস কনস্ট্রাক্টর থাকতে পারে না। স্ট্রাক্ট সদস্যরা স্বয়ংক্রিয়ভাবে তাদের ডিফল্ট মানগুলিতে আরম্ভ হয়।

স্ট্রাক্টের জন্য একটি ডিফল্ট (প্যারামিটার-কম) কনস্ট্রাক্টর অল-শূণিত রাষ্ট্রের চেয়ে আলাদা মান নির্ধারণ করতে পারে যা অপ্রত্যাশিত আচরণ হবে। .NET রানটাইম স্ট্রাক্টের জন্য ডিফল্ট কনস্ট্রাক্টরকে নিষিদ্ধ করে।


এই উত্তর এখন পর্যন্ত সেরা। শেষ পর্যন্ত সীমাবদ্ধতার পুরো বিষয়টি হ'ল আপনি যে MyStruct s;ডিফল্ট কনস্ট্রাক্টরকে সরবরাহ করেছেন তা না ডাকে চমকে যাওয়া এড়ানো ।
talles

1
ব্যাখ্যা করার জন্য আপনাকে ধন্যবাদ. সুতরাং এটি কেবলমাত্র একটি সংকলকের অভাব যা উন্নতি করতে হবে, প্যারামিটারলেস নির্মাতাদের নিষেধ করার কোনও তাত্ত্বিক ভাল কারণ নেই (যত তাড়াতাড়ি তারা কেবল অ্যাক্সেস বৈশিষ্ট্যে সীমাবদ্ধ থাকতে পারে)।
এলো

16

আপনি একটি স্থিতিশীল সম্পত্তি তৈরি করতে পারেন যা একটি ডিফল্ট "যৌক্তিক" নম্বরটি আরম্ভ করে এবং প্রদান করে:

public static Rational One => new Rational(0, 1); 

এবং এটি ব্যবহার করুন:

var rat = Rational.One;

24
এই ক্ষেত্রে, Rational.Zeroএকটি বিট কম বিভ্রান্তিকর হতে পারে।
কেভিন

13

সংক্ষিপ্ত ব্যাখ্যা:

সি ++ তে স্ট্রাক্ট এবং ক্লাস একই মুদ্রার মাত্র দুটি দিক ছিল। কেবল আসল পার্থক্যটি হ'ল একটি ডিফল্টরূপে সর্বজনীন ছিল এবং অন্যটি ব্যক্তিগত ছিল।

ইন .NET , সেখানে একটি struct এবং একটি শ্রেণীর মধ্যে একটি অনেক বড় পার্থক্য আছে। মূল জিনিসটি হ'ল স্ট্রাক্ট মান-ধরণের শব্দার্থবিদ্যা সরবরাহ করে, যখন শ্রেণি রেফারেন্স-টাইপ শব্দার্থবিদ্যা সরবরাহ করে। আপনি যখন এই পরিবর্তনের প্রভাব সম্পর্কে চিন্তাভাবনা শুরু করেন, আপনার বর্ণনাকারীর ব্যবহার সহ অন্যান্য পরিবর্তনগুলি আরও তাত্পর্যপূর্ণ হতে শুরু করে।


7
মান বনাম রেফারেন্স টাইপ বিভাজন আমি এটি পাই না তার দ্বারা আপনাকে কীভাবে আরও স্পষ্ট করতে হবে ...
মোটি

মান ধরণের একটি ডিফল্ট মান থাকে - এগুলি বাতিল হয় না, এমনকি যদি আপনি কোনও নির্মাণকারীকে সংজ্ঞায়িত করেন না। প্রথম নজরে এটি কোনও ডিফল্ট কনস্ট্রাক্টরকে সংজ্ঞায়িত করা থেকে বিরত থাকে না, স্ট্রাক্টগুলি সম্পর্কে নির্দিষ্ট অনুমান করার জন্য এই বৈশিষ্ট্যটি অভ্যন্তরীণভাবে ব্যবহার করে।
জোয়েল কোহোর্ন 21

@ নানকাতা: অন্য নির্মাণকারীরা প্রতিচ্ছবি যুক্ত কিছু পরিস্থিতিতে সম্ভবত দরকারী। এছাড়াও, যদি জেনারিকগুলি কোনও প্যারামিটারাইজড "নতুন" সীমাবদ্ধতার অনুমতি দেওয়ার জন্য বাড়ানো হয়, তবে তাদের সাথে মেনে চলতে পারে এমন স্ট্রাক্টগুলি ব্যবহার করা কার্যকর হবে।
সুপারক্যাট

@ নানকাতা আমি বিশ্বাস করি এটি কারণ সি # এর একটি বিশেষ দৃ requirement় প্রয়োজনীয়তা রয়েছে যা newসত্যিকারের একজন কনস্ট্রাক্টরকে কল করতে লিখতে হবে। সি ++ এ কনস্ট্রাক্টরগুলিকে গোপন উপায়ে, অ্যারে ঘোষণা বা তাত্ক্ষণিক সময়ে ডাকা হয়। সি # তে সমস্ত কিছুই একটি পয়েন্টার তাই শূন্য থেকে শুরু করুন, হয় এটি স্ট্রাক্ট এবং অবশ্যই কিছু থেকে শুরু করা উচিত, তবে যখন আপনি লিখতে পারবেন না new... (অ্যারের ডিআইআই এর মতো), এটি একটি শক্তিশালী সি # নিয়ম ভেঙে ফেলবে।
v.oddou

3

আমি যে দেরিতে সমাধান দিতে যাচ্ছি তার সমতুল্য আমি দেখিনি, তাই এটি এখানে।

আপনার পছন্দসই মানতে ডিফল্ট 0 থেকে মানগুলি সরিয়ে নিতে অফসেট ব্যবহার করুন। এখানে বৈশিষ্ট্যগুলি সরাসরি অ্যাক্সেসের ক্ষেত্রগুলির পরিবর্তে ব্যবহার করা উচিত। (সম্ভবত সম্ভাব্য সি # 7 বৈশিষ্ট্যের সাহায্যে আপনি সম্পত্তি বিস্তৃত ক্ষেত্রগুলি আরও ভালভাবে সংজ্ঞায়িত করতে পারেন যাতে তারা সরাসরি কোডে অ্যাক্সেস করা থেকে সুরক্ষিত থাকে))

এই দ্রষ্টব্যটি কেবলমাত্র মান ধরণের (কোনও রেফ টাইপ বা নাল স্ট্রাক্ট নয়) সহ সাধারণ স্ট্রাক্টের জন্য কাজ করে।

public struct Tempo
{
    const double DefaultBpm = 120;
    private double _bpm; // this field must not be modified other than with its property.

    public double BeatsPerMinute
    {
        get => _bpm + DefaultBpm;
        set => _bpm = value - DefaultBpm;
    }
}

এটির চেয়ে আলাদা এই উত্তরের , এই পদ্ধতিরটি বিশেষ কেসিং নয় তবে এর অফসেট ব্যবহার করে যা সমস্ত ব্যাপ্তির জন্য কাজ করবে।

ক্ষেত্র হিসাবে enums সঙ্গে উদাহরণ।

public struct Difficaulty
{
    Easy,
    Medium,
    Hard
}

public struct Level
{
    const Difficaulty DefaultLevel = Difficaulty.Medium;
    private Difficaulty _level; // this field must not be modified other than with its property.

    public Difficaulty Difficaulty
    {
        get => _level + DefaultLevel;
        set => _level = value - DefaultLevel;
    }
}

যেমনটি আমি বলেছি যে এই কৌশলটি সব ক্ষেত্রেই কার্যকর না হতে পারে, এমনকি যদি স্ট্রাক্টের কেবলমাত্র মূল্য ক্ষেত্র থাকে তবে কেবল আপনিই জানেন যে এটি যদি আপনার ক্ষেত্রে কার্যকর হয় বা না হয়। শুধু পরীক্ষা। তবে আপনি সাধারণ ধারণা পেতে পারেন।


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

2

শুধু বিশেষ ক্ষেত্রে এটি। আপনি যদি 0 এর একটি সংখ্যক এবং 0 এর বিভাজন দেখতে পান তবে ভান করুন এটির মতো আপনার পছন্দ মতো মান রয়েছে।


5
আমি ব্যক্তিগতভাবে আমার ক্লাস / স্ট্রাক্টকে এই ধরণের আচরণ করতে চাই না। নিঃশব্দে ব্যর্থ হওয়া (বা আপনার পক্ষে দেব অনুমানের দিক থেকে পুনরুদ্ধার করা) অনাবৃত ভুলের রাস্তা।
বোরিস কলেনস

2
+1 এটি একটি ভাল উত্তর, কারণ মানের ধরণের জন্য আপনাকে তাদের ডিফল্ট মানটি বিবেচনা করতে হবে। এটি এর আচরণের সাথে আপনি ডিফল্ট মানটিকে "সেট" করতে দিন।
ইলিডানএস 4 মনিকাকে

তারা ঠিক যেমন ক্লাস বাস্তবায়িত করে Nullable<T>(যেমন int?)।
জোনাথন অ্যালেন

এটা খুব খারাপ ধারণা। 0/0 সর্বদা একটি অবৈধ ভগ্নাংশ (NaN) হওয়া উচিত। যদি কেউ কল করে new Rational(x,y)যেখানে x এবং y এর 0 হবে?
মাইক রোসফট

আপনার যদি সত্যিকারের নির্মাতা থাকে তবে আপনি একটি ব্যতিক্রম ছুঁড়ে ফেলতে পারেন, আসল 0/0 হওয়া থেকে বিরত রাখতে। অথবা আপনি যদি এটিটি চান তা করতে চান, আপনাকে ডিফল্ট এবং 0/0 এর মধ্যে পার্থক্য করতে একটি অতিরিক্ত বুল যোগ করতে হবে।
জোনাথন অ্যালেন

2

আমি যা ব্যবহার করি তা হল নাল-কোলেসিং অপারেটর (??) এর মতো ব্যাকিং ফিল্ডের সাথে মিলিত:

public struct SomeStruct {
  private SomeRefType m_MyRefVariableBackingField;

  public SomeRefType MyRefVariable {
    get { return m_MyRefVariableBackingField ?? (m_MyRefVariableBackingField = new SomeRefType()); }
  }
}

আশাকরি এটা সাহায্য করবে ;)

দ্রষ্টব্য: নাল কোলেসিং অ্যাসাইনমেন্ট বর্তমানে সি # 8.0 এর জন্য একটি বৈশিষ্ট্য প্রস্তাব।


1

আপনি ডিফল্ট কনস্ট্রাক্টর সংজ্ঞায়িত করতে পারবেন না কারণ আপনি সি # ব্যবহার করছেন।

.NET- তে স্ট্রাক্টের ডিফল্ট কনস্ট্রাক্টর থাকতে পারে, যদিও আমি এটির সমর্থন করে এমন কোনও নির্দিষ্ট ভাষা জানি না।


সি # তে, ক্লাস এবং স্ট্রাক্ট শব্দার্থগতভাবে পৃথক। কাঠামো একটি মান প্রকার, অন্যদিকে শ্রেণি একটি রেফারেন্স টাইপ।
টম সার্ডু

-1

কোনও ডিফল্ট কনস্ট্রাক্টর দ্বিধায় আমার সমাধান এখানে। আমি জানি এটি একটি দেরিযুক্ত সমাধান, তবে আমি মনে করি এটি সমাধান হিসাবে লক্ষ্য করা উচিত।

public struct Point2D {
    public static Point2D NULL = new Point2D(-1,-1);
    private int[] Data;

    public int X {
        get {
            return this.Data[ 0 ];
        }
        set {
            try {
                this.Data[ 0 ] = value;
            } catch( Exception ) {
                this.Data = new int[ 2 ];
            } finally {
                this.Data[ 0 ] = value;
            }
        }
    }

    public int Z {
        get {
            return this.Data[ 1 ];
        }
        set {
            try {
                this.Data[ 1 ] = value;
            } catch( Exception ) {
                this.Data = new int[ 2 ];
            } finally {
                this.Data[ 1 ] = value;
            }
        }
    }

    public Point2D( int x , int z ) {
        this.Data = new int[ 2 ] { x , z };
    }

    public static Point2D operator +( Point2D A , Point2D B ) {
        return new Point2D( A.X + B.X , A.Z + B.Z );
    }

    public static Point2D operator -( Point2D A , Point2D B ) {
        return new Point2D( A.X - B.X , A.Z - B.Z );
    }

    public static Point2D operator *( Point2D A , int B ) {
        return new Point2D( B * A.X , B * A.Z );
    }

    public static Point2D operator *( int A , Point2D B ) {
        return new Point2D( A * B.Z , A * B.Z );
    }

    public override string ToString() {
        return string.Format( "({0},{1})" , this.X , this.Z );
    }
}

নাল নামক একটি স্ট্যাটিক স্ট্রাক্ট এই বিষয়টিকে উপেক্ষা করে, (দ্রষ্টব্য: এটি কেবলমাত্র সমস্ত ধনাত্মক চতুষ্পদের জন্য) গেট; সেট ব্যবহার করে; সি # তে, আপনার ত্রুটিগুলি মোকাবেলার জন্য অবশেষে চেষ্টা / ধরা / থাকতে পারে যেখানে একটি নির্দিষ্ট ডেটা টাইপ ডিফল্ট কনস্ট্রাক্টর পয়েন্ট 2 ডি () দ্বারা আরম্ভ হয় না। আমার ধারণা এই উত্তরের কিছু লোকের সমাধান হিসাবে এটি অধরা el আমি কেন যোগ করছি বেশিরভাগ ক্ষেত্রে। সি # তে গিটার এবং সেটারের কার্যকারিতাটি ব্যবহার করা আপনাকে এই ডিফল্ট নির্মাতাকে অজ্ঞান করে বাইপাস করার অনুমতি দেবে এবং আপনি যেটি শুরু করলেন না তার চারপাশে চেষ্টা করার চেষ্টা করবে। আমার জন্য এটি ভাল কাজ করে, অন্য কারও পক্ষে আপনি বিবৃতি দিলে কিছু যুক্ত করতে পারেন। সুতরাং, আপনি যেখানে একটি সংখ্যক / ডিনোমিনেটর সেটআপ চান সেখানে এই কোডটি সহায়তা করতে পারে। আমি কেবল পুনরাবৃত্তি করতে চাই যে এই সমাধানটি দেখতে ভাল লাগছে না, সম্ভবত দক্ষতার দিক থেকে আরও খারাপ কাজ করে তবে, সি # এর পুরানো সংস্করণ থেকে আসা কারও জন্য অ্যারের ডেটা প্রকারগুলি ব্যবহার করা আপনাকে এই কার্যকারিতা দেয়। আপনি যদি কিছু কাজ করতে চান তবে এটি চেষ্টা করুন:

public struct Rational {
    private long[] Data;

    public long Numerator {
        get {
            try {
                return this.Data[ 0 ];
            } catch( Exception ) {
                this.Data = new long[ 2 ] { 0 , 1 };
                return this.Data[ 0 ];
            }
        }
        set {
            try {
                this.Data[ 0 ] = value;
            } catch( Exception ) {
                this.Data = new long[ 2 ] { 0 , 1 };
                this.Data[ 0 ] = value;
            }
        }
    }

    public long Denominator {
        get {
            try {
                return this.Data[ 1 ];
            } catch( Exception ) {
                this.Data = new long[ 2 ] { 0 , 1 };
                return this.Data[ 1 ];
            }
        }
        set {
            try {
                this.Data[ 1 ] = value;
            } catch( Exception ) {
                this.Data = new long[ 2 ] { 0 , 1 };
                this.Data[ 1 ] = value;
            }
        }
    }

    public Rational( long num , long denom ) {
        this.Data = new long[ 2 ] { num , denom };
        /* Todo: Find GCD etc. */
    }

    public Rational( long num ) {
        this.Data = new long[ 2 ] { num , 1 };
        this.Numerator = num;
        this.Denominator = 1;
    }
}

2
এটি খুব খারাপ কোড। আপনার স্ট্রাক্ট এ অ্যারে রেফারেন্স কেন? আপনার কেবল ক্ষেত্র হিসাবে X এবং Y স্থানাঙ্ক নেই কেন? এবং প্রবাহ নিয়ন্ত্রণের জন্য ব্যতিক্রমগুলি ব্যবহার করা একটি খারাপ ধারণা; আপনার কোডটি সাধারণত আপনার কোডটি এমনভাবে লিখতে হবে যাতে নুলরফারেন্সেক্সেক্সেশনটি ঘটে না। যদি আপনার সত্যিই এটির প্রয়োজন হয় - যদিও এ জাতীয় নির্মাণ কাঠামোর চেয়ে কোনও শ্রেণীর পক্ষে উপযুক্ত হবে - তবে আপনার অলস সূচনাটি ব্যবহার করা উচিত। (এবং প্রযুক্তিগতভাবে, আপনি সম্পূর্ণরূপে অকারণে তবে স্থানাঙ্কের প্রথম সেটিং - প্রতিটি সমন্বয়কে দু'বার নির্ধারণ করেন।)
মাইক রোসফট

-1
public struct Rational 
{
    private long numerator;
    private long denominator;

    public Rational(long num = 0, long denom = 1)   // This is allowed!!!
    {
        numerator   = num;
        denominator = denom;
    }
}

5
এটি অনুমোদিত তবে কোনও প্যারামিটার নির্দিষ্ট না করা হলে এটি ব্যবহার করা হবে না আদর্শ one.com/xsLloQ
মোটি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.