物业支持价值范围

这样的事情可能吗? 我假设没有,但它对我来说很好看

class MyClass { public int Foo { get { return m_foo; } set { // Bounds checking, or other things that prevent the use // of an auto-implemented property m_foo = value; } // Put the backing field actually *in* the scope of the property // so that the rest of the class cannot access it. private int m_foo; } void Method() { m_foo = 42; // Can't touch this! } } 

当然我知道这个语法不正确,这不会编译。 为了清楚地描绘我的想法,这是假设的未来C#。 我为这个有点假设的问题道歉,但它对于Programmers.SE来说太具体了。

这样的东西可以在编译器中实现,它可以用于一个目的:只允许属性的getset访问器查看字段,实质上允许属性是自包含的(如自动实现的属性),同时允许额外的get /设定逻辑。

简短的回答是否定的,今天在C#中是不可能的。

我们经常收到这样的function请求; 它的更通用的forms是一个很好的function。 更一般的forms是更清楚地使局部变量的寿命与其范围正交。

只是为了确保这些术语是明确的: 变量是一个存储位置,可能是名称。 每个变量都有一个生命周期 :运行时保证变量引用有效存储的时间量。 名称范围是可以使用该名称的文本区域; 它是一个编译时的概念,而不是运行时概念。 局部变量是一个变量,其范围语句块

在许多语言中,局部变量的生命周期与其范围紧密相关:当控制在运行时逻辑上进入范围时,生命周期开始,当它离开范围时,生命周期结束。 在C#中也是如此,但有一些值得注意的警告:

  • 如果运行时可以确定这样做对托管代码对当前线程的操作没有影响,则可以扩展或截断本地的生存期。 其他线程(如终结器线程)和当前线程上的非托管代码的操作是实现定义的。

  • 迭代器块,异步方法或匿名函数的封闭外部变量中的本地生存期可以扩展为匹配或超过使用它的迭代器,任务,委托或表达式树的生命周期。 。

显然,并不要求本地的生命周期和范围以任何方式捆绑在一起。 如果我们可以明确地拥有具有实例或静态字段的生命周期的本地人,但是本地的范围,那将是很好的。 C有这个function; 你可以创建一个“静态”局部变量。 C#没有。 您的提议主要是允许属性块中的局部变量具有实例的生存期,但其范围仅限于块。

我会将此function归类为“不错”。 我们有一个潜在的“好”function列表,只要你的arm我们没有时间实现,所以我不希望这一个很快就能在列表的顶部。 谢谢你的反馈; 它有助于我们在某种程度上优先考虑该列表。

这是我对此的看法:

 public class WrappedField { public class Internals { public T Value; } private readonly Internals _internals = new Internals(); private readonly Func _get; private readonly Action _set; public T Value { get { return _get(_internals); } set { _set(_internals, value); } } public WrappedField(Func get, Action set) { _get = get; _set = set; } public WrappedField(Func get, Action set, T initialValue) : this(get, set) { _set(_internals, initialValue); } } 

用法:

 class Program { readonly WrappedField _weight = new WrappedField( i => i.Value, // get (i, v) => i.Value = v, // set 11); // initialValue static void Main(string[] args) { Program p = new Program(); p._weight.Value = 10; Console.WriteLine(p._weight.Value); } } 

根据C#4.0语言规范。

但是,与字段不同,属性不表示存储位置 。 相反,属性具有访问器,用于指定在读取或写入值时要执行的语句。

添加字段需要内存位置。 所以不,这是不可能的。

如果您想避免使用generics,您可以始终隐藏_backingField和私有内部类中的边界检查。 您甚至可以通过使外部类部分隐藏它来进一步隐藏它。 当然,外部和内部类之间必须进行一些委托,这是一个无赖。 代码解释我的想法:

 public partial class MyClass { public int Property { get { return _properties.Property; } set { _properties.Property = value; } } public void Stuff() { // Can't get to _backingField... } } public partial class MyClass { private readonly Properties _properties = new Properties(); private class Properties { private int _backingField; public int Property { get { return _backingField; } set { // perform checks _backingField = value; } } } } 

但这是很多代码。 为了certificate所有锅炉板的合理性,最初的问题必须非常严重……

不,这个属性的唯一内容就是getset

好吧,它很难处理,可能不是很高效,而不是我真正使用的东西,但从技术上讲,这是一种模糊其他同类人员的支持领域的方法。

 public class MySuperAwesomeProperty { private T backingField; private Func getter; private Func setter; public MySuperAwesomeProperty(Func getter, Func setter) { this.getter = getter; this.setter = setter; } public T Value { get { return getter(backingField); } set { backingField = setter(value); } } } public class Foo { public MySuperAwesomeProperty Bar { get; private set; } public Foo() { Bar = new MySuperAwesomeProperty( value => value, value => { doStuff(); return value; }); Bar.Value = 5; Console.WriteLine(Bar.Value); } private void doStuff() { throw new NotImplementedException(); } }