C#中的幂等接口方法 - c#

我正在尝试创建一个接口,该接口返回实现它的实例的修改后的副本,并且不修改原始实例。

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', …