简体   繁体   English

c#中的幂等接口方法

[英]Idempotent interface method in c#

I am trying to create an interface that returns a modified copy of an instance that implements it and does not modify the original instance.我正在尝试创建一个接口,该接口返回实现它的实例的修改副本并且不修改原始实例。

public interface ICensoreable<T> {
    T GetCensored();
}

And the object that implements以及实现的对象

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;
    }
}

Is there any way to enforce on an interface that GetCensored will not modify User (or T) instance?有什么方法可以在 GetCensored 不会修改用户(或 T)实例的接口上强制执行?

With the recent release of C# 8.0, you can now define default method implementations in your interface.在最近发布的 C# 8.0 中,您现在可以在接口中定义默认方法实现。 Therefore, you will be able to enforce that by default the GetCensored() method does not modify the original instance.因此,您将能够在默认情况下强制执行GetCensored()方法不修改原始实例。 By marking the default implementation as sealed , the type that implements the interface is prohibited from explicitly reimplementing the method.通过将默认实现标记为sealed ,禁止实现该接口的类型显式地重新实现该方法。 Since the method is only implemented in the interface, you need to cast the object to ICensoreable<T> before calling the GetCensored() method.由于该方法仅在接口中实现,因此您需要在调用GetCensored()方法之前将对象转换为ICensoreable<T>

This is the implementation that I used:这是我使用的实现:

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();
}

Using the GetCensored() method:使用GetCensored()方法:

var user = new User();
var censored = ((ICensoreable<User>)user).GetCensored();

NOTE: As of the time of writing, this implementation will throw a NullReferenceException at the first line of the GetCensored() method (using C# 8.0 on VS 16.4.0 Preview 2.0). 注意:截至撰写本文时,此实现 GetCensored()方法的第一行抛出 NullReferenceException (在 VS 16.4.0 预览版 2.0 上使用 C# 8.0)。 I personally assume this is a bug, since removing the sealed keyword will not cause any issues whatsoever with the exact same code. 我个人认为这是一个错误,因为删除 sealed关键字不会对完全相同的代码造成任何问题。 Furthermore, I tried another implementation which involved initializing a new object of type T , which also crashed. 此外,我尝试了另一种实现,其中涉及初始化类型为 T的新对象,该对象也崩溃了。 The line was var result = new T(); 该行是 var result = new T(); and it threw a NullReferenceException . 它抛出了一个 NullReferenceException This is fixed in VS 16.5.4 onwards and the code runs correctly.这在 VS 16.5.4 及更高版本中得到修复,代码运行正常。

Theoretically, and as per the proposal, the sealed keyword simply prevents types from overriding the interface method and only keeping the default implementation.从理论上讲,根据提案, sealed关键字只是防止类型覆盖接口方法并且只保留默认实现。

EDIT 1: Currently at VS 16.4.0 Preview 5.0, the exception being thrown is AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'编辑 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.' AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.' . . After investigating a bit I realized that the bug has been known for a few weeks with a relevant GitHub issue .经过一番调查后,我意识到这个错误已经为人所知几周了,并且有一个相关的GitHub 问题 In accordance with somebody this is fixed in 16.5.0 Preview 1.0 onwards, after a follow-up fix .据某人称,在后续修复后,此问题已在 16.5.0 Preview 1.0 之后修复

EDIT 2: Currently at VS 16.5.0 Preview 1.0, the exception is still the same;编辑 2:目前在 VS 16.5.0 预览版 1.0 中,异常仍然相同; there was no fix for this issue being released yet.尚未发布此问题的修复程序。

FINAL EDIT: From VS 16.5.4 onwards (I hope), this code works just fine.最终编辑:从 VS 16.5.4 开始(我希望),这段代码工作得很好。 No exception is being thrown.没有异常被抛出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM