C#中的幂等接口方法

Dan*_*iel 6 c# oop interface

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

public interface ICensoreable<T> {
    T GetCensored();
}
Run Code Online (Sandbox Code Playgroud)

和实现的对象

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

有什么方法可以 GetCensored不会修改User(或T)实例的接口上强制执行?

Rek*_*kon 4

随着最近发布的 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();
}
Run Code Online (Sandbox Code Playgroud)

使用GetCensored()方法:

var user = new User();
var censored = ((ICensoreable<User>)user).GetCensored();
Run Code Online (Sandbox Code Playgroud)

注意:截至撰写本文时,此实现NullReferenceException在方法的第一行抛出 a 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 问题一起存在了几周。根据某人的说法,在后续修复后,此问题已在 16.5.0 Preview 1.0 中修复

编辑2:目前在VS 16.5.0 Preview 1.0,异常仍然是相同的;目前尚未发布针对此问题的修复方案。

最终编辑:从 VS 16.5.4 开始(我希望),这段代码工作得很好。没有抛出异常。