Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#/.Net中表示线性类型?_.net_Linear Types - Fatal编程技术网

如何在C#/.Net中表示线性类型?

如何在C#/.Net中表示线性类型?,.net,linear-types,.net,Linear Types,是否有一种合理的方式来表达in.Net(Compact Framework/desktop 3.5 common subset)的概念,使(a)所需的语法不会变得过于冗长、复杂或痛苦,(b)不变量可以在运行时强制执行,也可以在编译时通过代码分析验证(因此,一个急急忙忙的维护程序员不能只是轻率地忽略不变量)?这里的想法是为了避免在子系统边界进行防御性复制。提供的链接实际上定义了LinearVariable,其定义类似于: 选项显式打开 选项严格限制在 选项推断 _ (T的)线性变量类 私有枚举状态

是否有一种合理的方式来表达in.Net(Compact Framework/desktop 3.5 common subset)的概念,使(a)所需的语法不会变得过于冗长、复杂或痛苦,(b)不变量可以在运行时强制执行,也可以在编译时通过代码分析验证(因此,一个急急忙忙的维护程序员不能只是轻率地忽略不变量)?这里的想法是为了避免在子系统边界进行防御性复制。

提供的链接实际上定义了LinearVariable,其定义类似于:

选项显式打开
选项严格限制在
选项推断
_
(T的)线性变量类
私有枚举状态
未分配
分配
使用
结束枚举
Private _stateas state=state.Unassigned
私有值作为T
公共分新()
'允许创建和以后分配
端接头
公共子新建(ByVal值为T)
_价值=价值
_state=state.Assigned
端接头
公共共享加宽运算符CType(值为T)作为线性变量(共T个)
返回新的线性变量(共T个)(值)
终端操作员
公共共享加宽运算符CType(值为LinearVariable(Of T))为T
返回值
终端操作员
公共财产价值
得到
如果_state=state.Assigned,则
_状态=状态。已使用
#如果调试,则
返回值
#Else的释放-使用后立即释放引用
值=\u值
_值=零
#如果结束
如果结束
如果_state=state.Unassigned,则_
抛出新的NullReferenceException(“LinearVariable未赋值”)
如果_state=state,则使用_
抛出新的AccessViolationException(“LinearVariable已被访问”)
抛出新的InvalidOperationException
结束
设置(ByVal值为T)
'可能要检查_状态,尽管http://c2.com/cgi/wiki?LinearTypes 似乎允许多次写入
_价值=价值
_state=state.Assigned
端集
端属性
末级
(已编译但未经测试。)

这显然只在运行时起作用。我想不出任何方法可以在编译时强制使用
.Value


请注意,您可以将
线性变量设置为可
IDisposable
,然后在运行时捕获其值已设置且未使用的情况。

线性类型基于线性逻辑理论,与唯一性类型密切相关,是指分配给值的类型,这些值的属性是它们在任何时候都只有一个引用imes。它们对于描述大型不可变值(如文件、字符串等)很有价值

不可变类型是指内部状态在实例化后无法更改的类型

“深度不可变”类型是指其依赖关系图包含的引用类型也是“深度不可变”的类型。如果依赖引用类型本身不是“深度不可变”,则该类型称为“浅不可变”

在C#中,我们使用引用类型和值类型。引用类型的实例可以在不同的并发执行代码之间共享,而值类型是堆栈绑定的(除非装箱),在共享时复制,因此是自治的,尽管不是不变的(并且可能包含对其他引用类型的依赖,这些引用类型随后是“复制共享”)

尽管共享引用类型的能力无疑是面向对象框架的一个强大功能,但在企业开发领域,它也应被视为其主要弱点之一,并应极其谨慎地使用。任何无法原子化执行的操作都会暴露出脆弱性,并有可能将错误交错在一起断断续续地造成严重破坏

在C#中,我们所能做的最好的事情就是描述我们的意图。通过将整个内部状态标记为私有和只读,可以部分实现不变性。深度不变性不能强制(也不能因此而变浅)因此,由开发人员来坚持意图。对状态的更改是通过静态方法进行的,这些方法返回包含请求状态的类型的新实例

public sealed class PersonImmutable {

    private readonly int _age;
    private readonly string _name;

    public PersonImmutable(int age, string name) { 
        this._age = age;
        this._name = name;
    }

    public int Age {
        get { return this._age; }
    }

    public string Name {
        get { return this._name; }
    }

    public static PersonImmutable NotifyBirthday(PersonImmutable source) {
        return new PersonImmutable(1 + source.Age, source.Name);
    }
}

Net中有两种类型:引用类型和值类型

通过将引用类型指定给另一个变量来复制引用类型时,只复制引用

复制值类型时,将逐字节复制该类型的全部内容

在这两种情况下,都没有办法阻止、修改或获取关于它的通知(与C++的复制构造函数相反),这意味着不能在.Net中实现线性类型


您可以像其他人建议的那样使用不可变(或可自由化)类型。

仅使用不可变对象就足够了吗?看起来简单多了?我不知道有什么可以进行必要的代码分析here@Marc“冰棒”不变性(组成一个可变对象子图,然后“冻结”它以防止进一步的变异)可能有用。我可能可以很容易地卷起一个FxCop规则来验证它。Freezable类呢?或者它不适用于您的用例?@Jeffrey-我经常使用冰棒不变性;比“构建器”简单得多类。@Mike谢谢你的提示!非常有趣的类。它是WPF的一部分,但在Compact Framework中不受支持,因此我必须重新实现它,可能没有依赖属性和更改通知包,并且具有比每线程更好的上下文区分。这不提供捕获对行的别名引用arVariable wrapper本身,也没有提供任何方法来防止保留对分配到变量中的对象的引用。@JeffreyHantin:是的,正如我所说,这只是一项运行时工作。我非常确定您需要编译器支持才能获得这些东西。具体地说,您可以获得一个FxCop规则,该规则会注意到变量的别名
LinearVariable
(实际上,它应该仅作为变量声明而不是参数存在