C#的只读(类似于“ const”的)函数参数 [英] Read-only ("const"-like) function parameters of C#

查看:98
本文介绍了C#的只读(类似于“ const”的)函数参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来自C ++背景,我习惯将 const 关键字粘贴到函数定义中,以使对象以只读值传递。但是,我发现这在C#中是不可能的(如果我错了,请纠正我)。经过一番谷歌搜索后,我得出的结论是,制作只读对象的唯一方法是编写一个仅具有 get属性的接口,并将其传递给它。

Coming from a C++ background, I'm used to sticking the const keyword into function definitions to make objects being passed in read-only values. However, I've found out that this is not possible in C# (please correct me if I'm wrong). After some Googling, I arrived at the conclusion that the only way to make a read-only object is to write an interface that only has 'get' properties and pass that in instead. Elegant, I must say.

public interface IFoo
{
  IMyValInterface MyVal{ get; }
}

public class Foo : IFoo
{
  private ConcreteMyVal _myVal;

  public IMyValInterface MyVal
  {
    get { return _myVal; }
  }
}

我会将其传递给:

public void SomeFunction(IFoo fooVar)
{
  // Cannot modify fooVar, Excellent!!
}

这很好。但是,在我的其余代码中,我想正常地修改对象。在界面上添加设置属性会破坏我的只读限制。我可以在 Foo 中添加一个'set'属性(而不是 IFoo ),但是签名需要接口而不是接口一个具体的对象。我必须做一些强制转换。

This is fine. However, in the rest of my code, I would like to modify my object normally. Adding a 'set' property to the interface would break my read-only restriction. I can add a 'set' property to Foo (and not IFoo), but the signature expects an interface rather than a concrete object. I would have to do some casting.

// Add this to class Foo. Might assign null if cast fails??
set { _myVal = value as ConcreteMyVal; }

// Somewhere else in the code...
IFoo myFoo = new Foo;
(myFoo as Foo).MyFoo = new ConcreteMyVal();

是否有更优雅的方式复制 const 或设置只读的函数参数而不添加其他属性或函数?

Is there a more elegant way of replicating const or making read-only function parameters without adding another property or a function?

推荐答案

我认为您可能正在寻找解决方案涉及两个接口,其中一个接口从另一个接口继承:

I think you may be looking for a solution involving two interfaces in which one inherits from the other:

public interface IReadableFoo
{
    IMyValInterface MyVal { get; }
}

public interface IWritableFoo : IReadableFoo
{
    IMyValInterface MyVal { set; }
}

public class Foo : IWritableFoo 
{
    private ConcreteMyVal _myVal;

    public IMyValInterface MyVal
    {
        get { return _myVal; }
        set { _myVal = value as ConcreteMyVal; }
    }
}

然后,您可以声明参数类型为 tells的方法,无论是否计划更改变量:

Then you can declare methods whose parameter type "tells" whether it plans on changing the variable or not:

public void SomeFunction(IReadableFoo fooVar)
{
    // Cannot modify fooVar, excellent!
}

public void SomeOtherFunction(IWritableFoo fooVar)
{
    // Can modify fooVar, take care!
}

这类似于在C ++中类似于constness的编译时检查。正如埃里克·利珀特(Eric Lippert)正确指出的那样,这与不变性是相同的。但是,作为C ++程序员,我想您知道这一点。

This mimics compile-time checks similar to constness in C++. As Eric Lippert correctly pointed out, this is not the same as immutability. But as a C++ programmer I think you know that.

顺便说一句,如果您在类中声明属性的类型,则可以获得更好的编译时检查。作为 ConcreteMyVal 并分别实现接口属性:

By the way, you can achieve slightly better compile-time checking if you declare the type of the property in the class as ConcreteMyVal and implement the interface properties separately:

public class Foo : IWritableFoo 
{
    private ConcreteMyVal _myVal;

    public ConcreteMyVal MyVal
    {
        get { return _myVal; }
        set { _myVal = value; }
    }

    public IMyValInterface IReadableFoo.MyVal { get { return MyVal; } }
    public IMyValInterface IWritableFoo.MyVal
    {
        // (or use "(ConcreteMyVal)value" if you want it to throw
        set { MyVal = value as ConcreteMyVal; }
    }
}

这样,二传手只能通过以下方式抛出接口,但不能通过类访问。

This way, the setter can only throw when accessed through the interface, but not when accessed through the class.

这篇关于C#的只读(类似于“ const”的)函数参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆