- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我向一位程序员同事展示了这个结构,他们认为它应该是一个可变类。他们觉得没有空引用和根据需要更改对象的能力是不方便的。我真的很想知道是否还有其他原因使它成为一个可变类。
[Serializable]
public struct PhoneNumber : IEquatable<PhoneNumber>
{
private const int AreaCodeShift = 54;
private const int CentralOfficeCodeShift = 44;
private const int SubscriberNumberShift = 30;
private const int CentralOfficeCodeMask = 0x000003FF;
private const int SubscriberNumberMask = 0x00003FFF;
private const int ExtensionMask = 0x3FFFFFFF;
private readonly ulong value;
public int AreaCode
{
get { return UnmaskAreaCode(value); }
}
public int CentralOfficeCode
{
get { return UnmaskCentralOfficeCode(value); }
}
public int SubscriberNumber
{
get { return UnmaskSubscriberNumber(value); }
}
public int Extension
{
get { return UnmaskExtension(value); }
}
public PhoneNumber(ulong value)
: this(UnmaskAreaCode(value), UnmaskCentralOfficeCode(value), UnmaskSubscriberNumber(value), UnmaskExtension(value), true)
{
}
public PhoneNumber(int areaCode, int centralOfficeCode, int subscriberNumber)
: this(areaCode, centralOfficeCode, subscriberNumber, 0, true)
{
}
public PhoneNumber(int areaCode, int centralOfficeCode, int subscriberNumber, int extension)
: this(areaCode, centralOfficeCode, subscriberNumber, extension, true)
{
}
private PhoneNumber(int areaCode, int centralOfficeCode, int subscriberNumber, int extension, bool throwException)
{
value = 0;
if (areaCode < 200 || areaCode > 989)
{
if (!throwException) return;
throw new ArgumentOutOfRangeException("areaCode", areaCode, @"The area code portion must fall between 200 and 989.");
}
else if (centralOfficeCode < 200 || centralOfficeCode > 999)
{
if (!throwException) return;
throw new ArgumentOutOfRangeException("centralOfficeCode", centralOfficeCode, @"The central office code portion must fall between 200 and 999.");
}
else if (subscriberNumber < 0 || subscriberNumber > 9999)
{
if (!throwException) return;
throw new ArgumentOutOfRangeException("subscriberNumber", subscriberNumber, @"The subscriber number portion must fall between 0 and 9999.");
}
else if (extension < 0 || extension > 1073741824)
{
if (!throwException) return;
throw new ArgumentOutOfRangeException("extension", extension, @"The extension portion must fall between 0 and 1073741824.");
}
else if (areaCode.ToString()[1] == '9')
{
if (!throwException) return;
throw new ArgumentOutOfRangeException("areaCode", areaCode, @"The second digit of the area code cannot be greater than 8.");
}
else
{
value |= ((ulong)(uint)areaCode << AreaCodeShift);
value |= ((ulong)(uint)centralOfficeCode << CentralOfficeCodeShift);
value |= ((ulong)(uint)subscriberNumber << SubscriberNumberShift);
value |= ((ulong)(uint)extension);
}
}
public override bool Equals(object obj)
{
return obj != null && obj.GetType() == typeof(PhoneNumber) && Equals((PhoneNumber)obj);
}
public bool Equals(PhoneNumber other)
{
return this.value == other.value;
}
public override int GetHashCode()
{
return value.GetHashCode();
}
public override string ToString()
{
return ToString(PhoneNumberFormat.Separated);
}
public string ToString(PhoneNumberFormat format)
{
switch (format)
{
case PhoneNumberFormat.Plain:
return string.Format(@"{0:D3}{1:D3}{2:D4}{3:#}", AreaCode, CentralOfficeCode, SubscriberNumber, Extension).Trim();
case PhoneNumberFormat.Separated:
return string.Format(@"{0:D3}-{1:D3}-{2:D4} {3:#}", AreaCode, CentralOfficeCode, SubscriberNumber, Extension).Trim();
default:
throw new ArgumentOutOfRangeException("format");
}
}
public ulong ToUInt64()
{
return value;
}
public static PhoneNumber Parse(string value)
{
var result = default(PhoneNumber);
if (!TryParse(value, out result))
{
throw new FormatException(string.Format(@"The string ""{0}"" could not be parsed as a phone number.", value));
}
return result;
}
public static bool TryParse(string value, out PhoneNumber result)
{
result = default(PhoneNumber);
if (string.IsNullOrEmpty(value))
{
return false;
}
var index = 0;
var numericPieces = new char[value.Length];
foreach (var c in value)
{
if (char.IsNumber(c))
{
numericPieces[index++] = c;
}
}
if (index < 9)
{
return false;
}
var numericString = new string(numericPieces);
var areaCode = int.Parse(numericString.Substring(0, 3));
var centralOfficeCode = int.Parse(numericString.Substring(3, 3));
var subscriberNumber = int.Parse(numericString.Substring(6, 4));
var extension = 0;
if (numericString.Length > 10)
{
extension = int.Parse(numericString.Substring(10));
}
result = new PhoneNumber(
areaCode,
centralOfficeCode,
subscriberNumber,
extension,
false
);
return result.value != 0;
}
public static bool operator ==(PhoneNumber left, PhoneNumber right)
{
return left.Equals(right);
}
public static bool operator !=(PhoneNumber left, PhoneNumber right)
{
return !left.Equals(right);
}
private static int UnmaskAreaCode(ulong value)
{
return (int)(value >> AreaCodeShift);
}
private static int UnmaskCentralOfficeCode(ulong value)
{
return (int)((value >> CentralOfficeCodeShift) & CentralOfficeCodeMask);
}
private static int UnmaskSubscriberNumber(ulong value)
{
return (int)((value >> SubscriberNumberShift) & SubscriberNumberMask);
}
private static int UnmaskExtension(ulong value)
{
return (int)(value & ExtensionMask);
}
}
public enum PhoneNumberFormat
{
Plain,
Separated
}
最佳答案
处理电话号码的程序是进程的模型。
因此,让流程中不可变的东西在代码中不可变。使流程中可变的东西在代码中可变。
例如,一个流程可能包括一个人。一个人有一个名字。一个人可以更改他们的名字,同时保留他们的身份。因此,人对象的名字应该是可变的。
一个人有一个电话号码。一个人可以更改他们的电话号码,同时保留他们的身份。因此,一个人的电话号码应该是可变的。
电话号码有区号。电话号码不能更改其区号并保留其身份;你改变区号,你现在有一个不同的电话号码。因此,电话号码的区号应该是不可变的。
关于c# - 这个不可变结构应该是一个可变类吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2465766/
我目前正在尝试基于哈希表构建字典。逻辑是:有一个名为 HashTable 的结构,其中包含以下内容: HashFunc HashFunc; PrintFunc PrintEntry; CompareF
如果我有一个指向结构/对象的指针,并且该结构/对象包含另外两个指向其他对象的指针,并且我想删除“包含这两个指针的对象而不破坏它所持有的指针”——我该怎么做这样做吗? 指向对象 A 的指针(包含指向对象
像这样的代码 package main import "fmt" type Hello struct { ID int Raw string } type World []*Hell
我有一个采用以下格式的 CSV: Module, Topic, Sub-topic 它需要能够导入到具有以下格式的 MySQL 数据库中: CREATE TABLE `modules` ( `id
通常我使用类似的东西 copy((uint8_t*)&POD, (uint8_t*)(&POD + 1 ), back_inserter(rawData)); copy((uint8_t*)&PODV
错误 : 联合只能在具有兼容列类型的表上执行。 结构(层:字符串,skyward_number:字符串,skyward_points:字符串)<> 结构(skyward_number:字符串,层:字符
我有一个指向结构的指针数组,我正在尝试使用它们进行 while 循环。我对如何准确初始化它并不完全有信心,但我一直这样做: Entry *newEntry = malloc(sizeof(Entry)
我正在学习 C,我的问题可能很愚蠢,但我很困惑。在这样的函数中: int afunction(somevariables) { if (someconditions)
我现在正在做一项编程作业,我并没有真正完全掌握链接,因为我们还没有涉及它。但是我觉得我需要它来做我想做的事情,因为数组还不够 我创建了一个结构,如下 struct node { float coef;
给定以下代码片段: #include #include #define MAX_SIZE 15 typedef struct{ int touchdowns; int intercepti
struct contact list[3]; int checknullarray() { for(int x=0;x<10;x++) { if(strlen(con
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Empty “for” loop in Facebook ajax what does AJAX call
我刚刚在反射器中浏览了一个文件,并在结构构造函数中看到了这个: this = new Binder.SyntaxNodeOrToken(); 我以前从未见过该术语。有人能解释一下这个赋值在 C# 中的
我经常使用字符串常量,例如: DICT_KEY1 = 'DICT_KEY1' DICT_KEY2 = 'DICT_KEY2' ... 很多时候我不介意实际的文字是什么,只要它们是独一无二的并且对人类读
我是 C 的新手,我不明白为什么下面的代码不起作用: typedef struct{ uint8_t a; uint8_t* b; } test_struct; test_struct
您能否制作一个行为类似于内置类之一的结构,您可以在其中直接分配值而无需调用属性? 前任: RoundedDouble count; count = 5; 而不是使用 RoundedDouble cou
这是我的代码: #include typedef struct { const char *description; float value; int age; } swag
在创建嵌套列表时,我认为 R 具有对列表元素有用的命名结构。我有一个列表列表,并希望应用包含在任何列表中的每个向量的函数。 lapply这样做但随后剥离了列表的命名结构。我该怎么办 lapply嵌套列
我正在做一个用于学习目的的个人组织者,我从来没有使用过 XML,所以我不确定我的解决方案是否是最好的。这是我附带的 XML 文件的基本结构:
我是新来的 nosql概念,所以当我开始学习时 PouchDB ,我找到了这个转换表。我的困惑是,如何PouchDB如果可以说我有多个表,是否意味着我需要创建多个数据库?因为根据我在 pouchdb
我是一名优秀的程序员,十分优秀!