【C#】提高枚举的灵活性和可扩展性

英文原文

https://www.jacksondunstan.com/articles/3290

 枚举擅长创建具有特定值的简单整数类型。它们的主要用途是从许多类似

enum Color { Red, Green, Blue }

的值中选择一个值。但是,如果你在这些选择上附加了数据,那该怎么办呢?如果数据是一种类型用于一种选择,而另一种类型用于另一种选择,该怎么办?如果有两条数据要附加到一个选项,而另一个选项只附加了一个,该怎么办?今天的文章展示了一个简单的模式,您可以在这些情况下使用它来代替枚举,以获得更大的灵活性和可扩展性。请继续阅读,看看如何做到这一点!
 假设您有一个登录功能,可以让用户登录到服务器:

void Login(string username, string password, Action<bool> callback);

 回调参数成功时调用TRUE,失败时调用FALSE。您通常很快就会意识到,简单的bool不足以表达登录时可能发生的所有错误。下面是您切换到枚举的版本:

enum LoginError
{	
	Success,	
	InvalidCredentials,	
	AccountLocked,	
	TemporarilyBanned,	
	PermanentlyBanned,
} 
void Login(string username, string password, Action<LoginError> callback);

 这比简单的bool要好得多,因为我们可以指定发生了什么类型的错误,而不是简单的“true”或“false”。这可能会对向用户报告错误有很大帮助。这肯定会对可扩展性有很大帮助,因为我们可以在发现错误类型时向枚举添加更多错误类型,而无需更改Login函数的函数签名。

 当我们想要将数据附加到这些枚举时,这个简单的枚举就开始出现问题。对于InvalidCredentials,在锁定其帐户之前允许用户再尝试多少次?对于AccountLocked和TemporarilyBanned,这种情况会持续多久?对于临时禁止和永久禁止,禁止的原因是什么?

 实际上,我们希望这些类型中的每一个都有一个类,这样我们就有地方放置一个或多个与错误相关的数据。以下是他们查找这些错误的方式:

class InvalidCredentials
{
	int RemainingAttempts;
}
 
class AccountLocked
{
	DateTime UnlockDate;
}
 
class TemporarilyBanned
{
	DateTime UnbanDate;
	string Reason;
}
 
class PermanentlyBanned
{
	string Reason;
}

 你可能会想到更多的字段来添加-禁止日期,账户锁定原因,凭证提示-现在有了一个非常方便的地方来放置它们。如果您也想为成功案例添加一些数据,您甚至可以为其创建一个类。唯一的问题是Login函数的回调参数不能有四种不同的类类型。您不知道会提前得到什么样的错误,所以您甚至不能重载该函数四次。相反,我们需要使用它们都实现的空接口将它们组合在一起:

interface ILoginError
{
}
 
class InvalidCredentials : ILoginError
{
	int RemainingAttempts;
}
 
class AccountLocked : ILoginError
{
	DateTime UnlockDate;
}
 
class TemporarilyBanned : ILoginError
{
	DateTime UnbanDate;
	string Reason;
}
 
class PermanentlyBanned : ILoginError
{
	string Reason;
}

 现在登录函数的回调可以使用ILoginError:

void Login(string username, string password, Action<ILoginError> callback);

 不指定枚举值,而是按如下方式创建错误:

new PermanentlyBanned { Reason = "Cheating" };

 在处理错误时,您需要检查每个可能的原因,就像使用枚举一样:

void HandleLogin(ILoginError error)
{
	if (error == null)
	{
		Debug.Log("Success");
		return;
	}
 
	var invalidCredentials = error as InvalidCredentials;
	if (invalidCredentials != null)
	{
		Debug.LogError(
			"Invalid credentials. You have " + invalidCredentials.RemainingAttempts + " more tries."
		);
	}
 
	var accountLocked = error as AccountLocked;
	if (accountLocked != null)
	{
		Debug.LogError(
			"Account locked until " + accountLocked.UnlockDate + "."
		);
	}
 
	var temporarilyBanned = error as TemporarilyBanned;
	if (temporarilyBanned != null)
	{
		Debug.LogError(
			"Banned until " + temporarilyBanned.UnbanDate + " for " + temporarilyBanned.Reason + "."
		);
	}
 
	var permanentlyBanned = error as PermanentBanned;
	if (permanentlyBanned != null)
	{
		Debug.LogError(
			"Banned for " + permanentlyBanned.Reason + "."
		);
	}
}

 这里有三个级别的指定错误:布尔、枚举、类。到目前为止,类方法比bool或enum更灵活和可扩展。它也需要最多的工作来设置,但这在很大程度上是因为您想要指定额外的数据。枚举和bool也是如此:与仅使用true和false相比,使用enum指定错误类型需要更多的设置。
 哪一级最适合你?只有你才能决定。你在你的应用程序中使用哪些?在评论中分享你的想法!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值