简体   繁体   English

将C#中的常量对象作为参数

[英]Const Objects in C# as Parameter

In C++, you can pass into a function an object that is const. 在C ++中,可以将const对象传递给函数。 This forces the code to treat that object as 'read only' (ignoring the fact that you can strip constness away using casts). 这迫使代码将该对象视为“只读”(忽略了可以使用强制类型转换常量性的事实)。 I'm trying to do the same with C#. 我正在尝试使用C#执行相同的操作。 I have an interface that the user will implement. 我有一个用户将实现的接口。 One of the methods will be given an object as a parameter. 其中一种方法将被赋予一个对象作为参数。 How do I make the object 'const' in the scope of the method and mutable otherwise. 我如何在方法范围内使对象为“ const”,否则为可变对象。

Solution: interfaces. 解决方案:接口。 I make an interface where the only action available on a property, is 'get'. 我创建一个接口,其中对属性唯一可用的操作是“ get”。

public interface IVal { ... }


public interface IFoo
{
    IVal Val { get; }
}

public class Foo : IFoo
{
    public IVal Val { get; }
}

I pass by interface and everything is amazing. 我通过界面,一切都很棒。 However, in my concrete class, I would like to have a 'set' available. 但是,在我的具体课程中,我希望有一个“设置”。 It would allow me to set a concrete class Value. 这将允许我设置一个具体的类Value。 How would my concrete class look like? 我的具体班级怎么样?

I was thinking of using the 'internal' keyword. 我当时正在考虑使用“内部”关键字。 I read that it exposes the method/property to code within your own assembly. 我读到它在您自己的程序集中公开了代码的方法/属性。 Is this my answer? 这是我的答案吗?

EDIT: To illustrate this better, I added a setter that would automatically cast for me. 编辑:为了更好地说明这一点,我添加了一个会自动为我投射的二传手。 However, for each property, this is a lot of repetative code: 但是,对于每个属性,这是很多重复的代码:

private Val _val;
public IVal Val
{
    get { return this._val; }
    set { this._val = value as Val; }
}

You can just add the set and it will work fine: 您可以添加set ,它将正常工作:

public IValue Value { get; set; }

Like this, you can set the value if you have Foo , but not if you have IFoo . 这样,如果您具有Foo ,则可以设置该值,但如果您具有IFoo ,则不能设置。 Similar to the C++ case, if you have IFoo , you can cast to Foo (as long as the object actually is Foo ) and then use the setter. 与C ++情况类似,如果您具有IFoo ,则可以IFooFoo (只要对象实际上是Foo ),然后使用setter。

Another option is to make the setter protected or private : 另一种选择是使设置器protectedprivate

public IValue Value { get; private set; }

This allows you to make sure that only code in this class (or inherited classed in the case of protected ) can set the property. 这使您可以确保只有此类(或在protected的情况下为继承的类)中的代码才能设置属性。

Regarding internal : yes, it exposes the member only to code in the same assembly (and friend assemblies). 关于internal :是的,它仅将成员公开给同一程序集(和朋友程序集)中的代码。 But this is not used very often. 但这并不经常使用。 What is used (and useful) are internal types, which is even the default, if you don't specify that that class is public . 使用的(并且有用的)是内部类型,如果您不指定该类为public ,那么它甚至是默认类型。

This could help you with your problem. 这可以帮助您解决问题。 If you make Foo internal , a method in other assembly that has IFoo won't be able to set the property, even with casting. 如果将Foo internal设置为,则即使使用强制转换,其他程序集中具有IFoo也无法设置该属性。

Of course, the code could always use reflection to set the property. 当然,代码可以始终使用反射来设置属性。 But you shouldn't worry about that most of the time. 但是大多数时候您不必担心。

You can do similiar thing 你可以做类似的事情

public class ReadonlyTestClass {
 private readonly object _name;
 public ReadonlyTestClass(object name) {
   _name = name;
 }
 public object Name {get { return _name; }}
}

Or 要么

public class ReadonlyTestClass {
 public ReadonlyTestClass(object name) {
   this.Name = name;
 }
 public object Name {get; private set;}
}

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

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