我正在尝试创建一个接口,该接口返回实现它的实例的修改后的副本,并且不修改原始实例。
public interface ICensoreable<T> {
T GetCensored();
}
和实现的对象
public class User:ICensoreable<User> {
public User(User copyFrom) {
this.name = copyFrom.name;
this.password = copyFrom.password;
}
public string name;
public string password;
public User GetCensored() {
User result = new User(this);
result.password = null;
return result;
}
}
是否有任何方法可以在接口上强制GetCensored不会修改User(或T)实例?
参考方案
使用最新版本的C#8.0,您现在可以在界面中定义默认方法实现。因此,您将能够强制默认情况下GetCensored()
方法不会修改原始实例。通过将默认实现标记为sealed
,禁止实现该接口的类型显式重新实现该方法。由于该方法仅在接口中实现,因此您需要在调用ICensoreable<T>
方法之前将对象强制转换为GetCensored()
。
这是我使用的实现:
public interface ICensoreable<T>
{
sealed ICensoreable<T> GetCensored()
{
var result = Clone();
result.CensorInformation();
return result;
}
ICensoreable<T> Clone();
void CensorInformation();
}
public class User : ICensoreable<User>
{
public User(User other)
{
name = other.name;
password = other.password;
}
public string name;
public string password;
public void CensorInformation()
{
password = null;
}
public User Clone() => new User(this);
ICensoreable<User> ICensoreable<User>.Clone() => Clone();
}
使用GetCensored()
方法:
var user = new User();
var censored = ((ICensoreable<User>)user).GetCensored();
~~注意:截至撰写本文时,此实现将在NullReferenceException
方法的第一行抛出一个GetCensored()
(在VS 16.4.0 Preview 2.0上使用C#8.0)。我个人认为这是一个错误,因为删除sealed
关键字对于完全相同的代码不会造成任何问题。此外,我尝试了另一种实现,其中涉及初始化类型为T
的新对象,该对象也崩溃了。该行是var result = new T();
,并抛出了NullReferenceException
。~~在VS 16.5.4及更高版本中已修复此问题,并且代码可以正确运行。
从理论上讲,按照建议,sealed
关键字只是防止类型覆盖接口方法,而仅保留默认实现。
编辑1:当前在VS 16.4.0 Preview 5.0中,抛出的异常是AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
。经过一番调查后,我意识到与相关的GitHub issue一起已知该错误已有数周了。根据某人的说法,在后续fix之后,此问题已在16.5.0 Preview 1.0及更高版本中修复。
编辑2:当前在VS 16.5.0预览版1.0,例外仍然是相同;目前尚无针对此问题的修复程序。
最终编辑:从VS 16.5.4起(我希望),此代码可以正常工作。没有异常被抛出。
与哪些运算符>>兼容 - java我这里没有什么代码int b=3; b=b >> 1; System.out.println(b); 它可以完美工作,但是当我将变量b更改为byte,short,float,double时,它包含错误,但是对于变量int和long来说,它可以完美工作,为什么它不能与其他变量一起工作? 参考方案 位移位运算符(例如>>)与任何整数类型兼…
为什么我无法更新字典中的test__user_id密钥? - python我正在更新包含数据的字典,dict_temp = {'description': 'hello', 'id': 683, 'status': u'pending', 'test__user_id': 430} 我试图使用dict_temp …
剃刀付款集成->如何通过关闭按钮X检测剃刀付款模型是否关闭 - javascript当用户关闭而无需付款时,我在CI框架中使用Razorpay,请创建razor支付模型,然后取消订单,我希望按状态更改为已取消的状态触发查询。所以我怎么能检测到这一点。我已经通过单击jQuery单击关闭功能但无法使用... javascript大神给出的解决方案 Razorpay提供了JS方法来检测模式关闭。您编写的任何JS代码都不会在结帐页面上运行,因为它是…
如何使用箭头符号(->)创建受保护的方法? - java当我们编写以下代码时Stream.of(1,2,3,4,5).filter(i -> (i%2 == 0)).map( i -> i*i ); 表达式i -> (i%2 == 0)或i -> i*i将变为私有方法。在我的用例中,编写了一个junit测试,以确保没有方法是私有的(是的,这是强制性的),并且对于这些lambda表达式而言,…
粗糙的Unicode->没有CLDR的语言代码? - javascript我在写字典应用。如果用户键入Unicode字符,我想检查该字符是哪种语言。例如字 - returns ['zh', 'ja', 'ko'] العربية - returns ['ar'] a - returns ['en', 'fr', …