概念定位:同一件事的两套表达
在面向对象编程中,类有私有数据(字段),外部不能直接读写。为了让外部安全地访问这些数据,需要提供"门"——在 LabVIEW 中叫 Data Accessor VI,在 C# 中叫 Property(属性)。
下表列出核心概念的对应关系:
| 概念 | LabVIEW | C# |
|---|---|---|
| 私有数据存储 | lvclass 私有数据簇中的控件 | private 字段 |
| 读取数据的入口 | Accessor VI(Read 模式) | get { return _field; } |
| 写入数据的入口 | Accessor VI(Write 模式) | set { _field = value; } |
| 最简单的创建方式 | 右键类 → New → VI for Data Member Access | 自动属性:{ get; set; } |
| 加入校验逻辑 | 在 Accessor VI 的 Block Diagram 中添加判断 | 在 set 块中写 if 判断 |
| 外部使用方式 | Property Node 或直接连线到 Accessor VI | obj.Property 直接读写 |
| 调用时的外观 | 像连线一个 VI | 像访问一个字段(语法透明) |
如果你在 LabVIEW 中创建过类并用过 Accessor VI,那么 C# 的属性在功能上完全对等——区别只在于 C# 把它内建到了语言层面,写起来更简洁。
最简形式:自动生成 vs 一行搞定
假设类Sensor有一个 Name(字符串)字段,需要外部可读可写,但不做任何校验。两边的做法如下:
public string Name { get; set; }编译器会自动生成隐藏的私有字段和默认的 get/set 方法体。等价于 LabVIEW 中自动创建了 Read Accessor 和 Write Accessor 两个 VI,只不过在 C# 中这一切是编译时完成的,不需要你手动创建 VI。
带逻辑形式:手写校验 vs set 代码块
实际项目中,属性往往需要在赋值时做校验。假设 Reading(温度读数)不能为负数——如果传入负值,应该报错。
private double _reading;
public double Reading
{
get { return _reading; }
set
{
if (value < 0)
throw new ArgumentException("读数不能为负");
_reading = value;
}
}“注意:在 LabVIEW 中 Accessor VI 内部抛出的错误是"原地处理"的(比如弹出对话框),而 C# 的 throw 是向调用方抛出异常。调用方需要 try-catch 来捕获。在 LabVIEW 互操作的 DLL 中,这个异常会自动映射为 LabVIEW 的 Error Cluster。”
完整对比:一个 Sensor 类的两种实现
下面把两边完整实现放在一起,对照着看:
┌──────────────────┐
│ Name : String │
│ Reading: DBL │
└──────────────────┘
自动生成的 Accessor VI:
• Read Name.vi
• Write Name.vi
• Read Reading.vi
• Write Reading.vi(需手写校验)
共 4 个 VI 文件
public class Sensor
{
// 自动属性:无校验
public string Name { get; set; }
// 带校验的属性
private double _reading;
public double Reading
{
get => _reading;
set
{
if (value < 0)
throw new ArgumentException(
"读数不能为负");
_reading = value;
}
}
}关键差异与注意事项
差异1:文件组织方式
LabVIEW 中每个 Accessor VI 都是一个独立的 .vi 文件,存在于磁盘上。一个类有 10 个属性,就是 20 个 VI 文件(读 + 写)。C# 中所有属性和方法都在同一个 .cs 文件中,逻辑上更聚合。
差异2:读写是否分离
LabVIEW 默认把 Read 和 Write 分成两个独立的 VI。C# 的 get 和 set 写在同一个属性声明中。如果需要只读属性,C# 只需省略 set:
public string Name { get; } // 只读
public double Reading { get; set; } // 可读可写差异3:get / set 的访问修饰符
C# 支持对 get 和 set 单独设置访问级别——这个能力 LabVIEW 不容易表达:
// 外部可读,但只能在类内部修改
public double Reading { get; private set; }差异4:value 是 C# 关键字
在 C# 的 set 块中,value 是一个上下文关键字,代表赋值时传进来的新值。它不需要声明,编译器自动识别。你在 LabVIEW 中看到的 "New Value" 输入端子,就是 C# 中的 value。
差异5:校验失败的处理方式
LabVIEW 通常在 Accessor VI 内部就地处理错误(弹窗、写 Error Cluster、或返回默认值)。C# 惯用的方式是通过 throw 抛异常,让调用方决定如何处理。在 LabVIEW 互操作的 DLL 中,C# 抛出的异常会自动转为 LabVIEW 的 Error Cluster,所以两者的体验最终是一致的。