在执行代码审查时,我找到了可以通过使用Null对象模式减少潜在错误的代码.然后我开始思考:如果该业务对象的默认值是空对象而不是空引用,那会不会有用?
由于C#提供了默认运算符,我试图像这样重载它:
public static MyObject operator default (MyObject object)
{
return MyObject.Null;
}
Run Code Online (Sandbox Code Playgroud)
这给了我错误:'可加载的一元运算符'.在进一步挖掘时,我发现文档的一部分说默认(T)是主要运算符:可重载运算符.
当你在上面的页面上实际点击默认值(T)时,默认是一个关键字.
最重要的是,此页面并未说默认值不可重载:可重载运算符(C#编程指南).
我知道这是一种学术,但我试图更深入地理解这种语言.什么是默认值(T)?它是运营商还是关键字?为什么不能超载(从语言设计的角度来看)?
更新:是的我已阅读C#语言规范第7.5.13节,我知道该语言的作用.我想知道为什么.
我遇到了一个有趣的设计问题,我正在写一个类库.我有一个AuthorizeAttribute的自定义实现,我希望客户能够像这样使用:
[Protected("permission_name")]
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,PermissionAttribute继承自AuthorizeAttribute并使用本地默认值(使用HttpContext创建的DefaultContext).
在幕后,该属性使用SecurityService来检查用户,角色和权限(SecurityService本身使用客户端提供的持久性服务,他们可以在应用程序的组合根中连接).
所以我的属性需要引用SecurityService才能运行.由于Attribute构造函数只能有编译时常量,所以我不能使用构造函数注入.
我不想强迫我的客户使用DI框架 - 如果他们愿意,他们应该能够在不使用IoC库的情况下发现并连接其组成根中的必要依赖项.
以下是我的选择:
上面2.的一个可能的解决方案是在应用程序启动时将SecurityService的实例设置为属性的静态属性,并使用guard子句来阻止它被设置多次,如下所示:
class ProtectedAttribute : ...
{
private static ISecurityService _SecurityService ;
public static ISecurityService SecurityService
{
get
{
return _SecurityService ;
}
set
{
if (_SecurityService != null)
throw new InvalidOperationException("You can only set the SecurityService once per lifetime of this app.") ;
_SecurityService = value ;
}
}
}
Run Code Online (Sandbox Code Playgroud)
SecurityService可以是抽象服务外观,以便可以通过不同的实现进行扩展/替换.
有没有更好的方法来解决这个问题?
更新:添加一些代码来说明我将如何做:
在返回权限名称的属性上添加公共属性:
public class ProtectedAttribute : ...
{
private string _Permission …Run Code Online (Sandbox Code Playgroud)