टीएल; डीआर: आमतौर पर एनमों के संग्रह का उपयोग करना एक बुरा विचार है क्योंकि यह अक्सर खराब डिजाइन की ओर जाता है। एनमों का एक संग्रह आमतौर पर विशिष्ट तर्क के साथ अलग-अलग सिस्टम संस्थाओं के लिए कहता है।
एनम के कुछ उपयोग मामलों के बीच अंतर करना आवश्यक है। यह सूची केवल मेरे सिर के ऊपर है इसलिए और भी मामले हो सकते हैं ...
उदाहरण सभी सी # में हैं, मुझे लगता है कि आपकी पसंद की भाषा में समान निर्माण होंगे या आपके लिए उन्हें स्वयं लागू करना संभव होगा।
1. केवल एकल मान मान्य है
इस स्थिति में, मान अनन्य हैं, जैसे
public enum WorkStates
{
Init,
Pending,
Done
}
यह कुछ काम है कि दोनों के लिए अमान्य है Pending
और Done
। इसलिए इनमें से केवल एक मान मान्य है। यह एनम का एक अच्छा उपयोग-मामला है।
2. मूल्यों का संयोजन वैध है
इस मामले को झंडे भी कहा जाता है, C # [Flags]
इन के साथ काम करने के लिए enum विशेषता प्रदान करता है । इस विचार को एक enum सदस्य के अनुरूप प्रत्येक के साथ bool
s या bit
s के सेट के रूप में तैयार किया जा सकता है । प्रत्येक सदस्य के पास दो की शक्ति का मूल्य होना चाहिए। बिटवाइज़ ऑपरेटरों का उपयोग करके संयोजन बनाए जा सकते हैं:
[Flags]
public enum Flags
{
None = 0,
Flag0 = 1, // 0x01, 1 << 0
Flag1 = 2, // 0x02, 1 << 1
Flag2 = 4, // 0x04, 1 << 2
Flag3 = 8, // 0x08, 1 << 3
Flag4 = 16, // 0x10, 1 << 4
AFrequentlyUsedMask = Flag1 | Flag2 | Flag4,
All = ~0 // bitwise negation of zero is all ones
}
Enum सदस्यों के संग्रह का उपयोग करना इस तरह के मामले में एक ओवरकिल है क्योंकि प्रत्येक enum सदस्य केवल एक बिट का प्रतिनिधित्व करता है जो या तो सेट है या परेशान है। मुझे लगता है कि अधिकांश भाषाएं इस तरह से निर्माण का समर्थन करती हैं। अन्यथा आप एक बना सकते हैं (जैसे इसका उपयोग करें bool[]
और इसे संबोधित करें (1 << (int)YourEnum.SomeMember) - 1
)।
a) सभी संयोजन मान्य हैं
हालांकि ये कुछ सरल मामलों में ठीक हैं, वस्तुओं का एक संग्रह अधिक उपयुक्त हो सकता है क्योंकि आपको अक्सर प्रकार के आधार पर अतिरिक्त जानकारी या व्यवहार की आवश्यकता होती है।
[Flags]
public enum Flavors
{
Strawberry = 1,
Vanilla = 2,
Chocolate = 4
}
public class IceCream
{
private Flavors _scoopFlavors;
public IceCream(Flavors scoopFlavors)
{
_scoopFlavors = scoopFlavors
}
public bool HasFlavor(Flavors flavor)
{
return _scoopFlavors.HasFlag(flavor);
}
}
(ध्यान दें: यह मानता है कि आप वास्तव में केवल आइसक्रीम के स्वाद के बारे में परवाह करते हैं - कि आपको स्कूप और शंकु के संग्रह के रूप में आइसक्रीम को मॉडल करने की आवश्यकता नहीं है)
बी) मूल्यों के कुछ संयोजन वैध हैं और कुछ नहीं
यह एक लगातार परिदृश्य है। मामला अक्सर यह हो सकता है कि आप दो अलग-अलग चीजों को एक एनम में डाल रहे हैं। उदाहरण:
[Flags]
public enum Parts
{
Wheel = 1,
Window = 2,
Door = 4,
}
public class Building
{
public Parts parts { get; set; }
}
public class Vehicle
{
public Parts parts { get; set; }
}
अब जबकि यह दोनों के लिए पूरी तरह से वैध है Vehicle
और Building
करने के लिए Door
है और Window
रों, है ना बहुत सामान्य के लिए है Building
रों है करने के लिए Wheel
है।
इस मामले में, किसी भी मामले # 1 या # 2a को प्राप्त करने के लिए एनम को भागों में तोड़ना और / या वस्तु पदानुक्रम को संशोधित करना बेहतर होगा।
रचना विवेचन
किसी तरह, एनओएम ओओ में ड्राइविंग तत्व नहीं होते हैं क्योंकि एक इकाई के प्रकार को उस जानकारी के समान माना जा सकता है जो आमतौर पर एक एनम द्वारा प्रदान की जाती है।
उदाहरण के लिए IceCream
# 2 से नमूना लें , IceCream
झंडे के बजाय इकाई में Scoop
वस्तुओं का संग्रह होगा ।
Scoop
एक Flavor
संपत्ति के लिए कम शुद्धतावादी दृष्टिकोण होगा । शुद्धतावादी दृष्टिकोण के लिए होगा Scoop
के लिए एक सार आधार वर्ग होने के लिए VanillaScoop
, ChocolateScoop
... कक्षाओं के बजाय।
लब्बोलुआब यह है कि:
1. वह सब कुछ नहीं है जो "एक प्रकार की चीज" है, उसे enum करने की आवश्यकता है
। 2. जब कुछ enum सदस्य कुछ परिदृश्य में एक वैध ध्वज नहीं है, तो enum को कई अलग-अलग Enums में विभाजित करने पर विचार करें।
अब आपके उदाहरण के लिए (थोड़ा बदला हुआ):
public enum Role
{
User,
Admin
}
public class User
{
public List<Role> Roles { get; set; }
}
मुझे लगता है कि इस सटीक मामले को मॉडल के रूप में देखा जाना चाहिए (ध्यान दें: वास्तव में एक्स्टेंसिबल नहीं है!):
public class User
{
public bool IsAdmin { get; set; }
}
दूसरे शब्दों में - यह निहित है, User
यह एक है User
, अतिरिक्त जानकारी है कि क्या वह एक है Admin
।
आप कई भूमिकाएं कि अनन्य नहीं हैं करने के लिए मिलता है (उदाहरण के लिए User
हो सकता है Admin
, Moderator
, VIP
, ... एक ही समय में), कि या तो झंडे Enum उपयोग करने के लिए एक अच्छा समय है या एक abtract आधार वर्ग या इंटरफ़ेस होगा।
Role
जिम्मेदारियों के बेहतर पृथक्करण की ओर ले जाने के लिए एक वर्ग का उपयोग करना जहां Role
यह तय करने की जिम्मेदारी हो सकती है कि क्या यह एक दिया गया कार्य कर सकता है।
एक पहेली के साथ आपको सभी भूमिकाओं के लिए एक जगह तर्क रखना होगा। जो OO के उद्देश्य को पराजित करता है और आपको अनिवार्य रूप से वापस लाता है।
कल्पना करें कि Moderator
अधिकारों का संपादन किया गया है और अधिकारों Admin
को संपादित और हटाना दोनों है।
एनम दृष्टिकोण ( Permissions
भूमिकाओं और अनुमतियों को नहीं मिलाने के लिए कहा जाता है):
[Flags]
public enum Permissions
{
None = 0
CanEdit = 1,
CanDelete = 2,
ModeratorPermissions = CanEdit,
AdminPermissions = ModeratorPermissions | CanDelete
}
public class User
{
private Permissions _permissions;
public bool CanExecute(IAction action)
{
if (action.Type == ActionType.Edit && _permissions.HasFlag(Permissions.CanEdit))
{
return true;
}
if (action.Type == ActionType.Delete && _permissions.HasFlag(Permissions.CanDelete))
{
return true;
}
return false;
}
}
क्लास एप्रोच (यह एकदम सही है, आदर्श रूप से, आप IAction
एक विज़िटर पैटर्न में चाहते हैं, लेकिन यह पोस्ट पहले से बहुत बड़ी है ...):
public interface IRole
{
bool CanExecute(IAction action);
}
public class ModeratorRole : IRole
{
public virtual bool CanExecute(IAction action)
{
return action.Type == ActionType.Edit;
}
}
public class AdminRole : ModeratorRole
{
public override bool CanExecute(IAction action)
{
return base.CanExecute(action) || action.Type == ActionType.Delete;
}
}
public class User
{
private List<IRole> _roles;
public bool CanExecute(IAction action)
{
_roles.Any(x => x.CanExecute(action));
}
}
एक एनुम का उपयोग एक स्वीकार्य दृष्टिकोण हो सकता है, हालांकि (उदाहरण के प्रदर्शन)। यहां निर्णय मॉडल प्रणाली की आवश्यकताओं पर निर्भर करता है।