C#索引器使用详解

在 C# 语法中,当.操作符后面直接跟随中括号[]时,这通常表示正在访问一个索引器 (Indexer)。索引器允许对象像数组或字典一样通过索引来访问其元素或值。然而,示例 bt.[BlockTableRecord.ModelSpace] 的写法是错误的,因为它试图将命名空间或类型名作为索引器的参数,这在语法上是不允许的。正确的用法需要将BlockTableRecord.ModelSpace作为一个明确的常量或属性值传递给索引器。

1. 核心概念:索引器访问

在 C# 中,索引器的使用格式为 object[index]。当它跟在.后面时,意味着我们正在访问某个对象实例的索引器。例如,对于一个字典或列表:

csharp 复制代码
// 假设 myDictionary 是一个 Dictionary<string, int>
int value = myDictionary["key"]; // 通过字符串索引访问值

// 假设 myList 是一个 List<string>
string item = myList[0]; // 通过整数索引访问元素

在 AutoCAD .NET API 的上下文中,BlockTable 对象有一个索引器,允许通过 ObjectId 或块名(作为字符串)来获取特定的 BlockTableRecord。因此,正确的访问方式应该是传入一个有效的键。

2. 错误示例分析:bt.[BlockTableRecord.ModelSpace]

这段代码意图是获取模型空间的块表记录,但语法是错误的:

  • BlockTableRecord.ModelSpace :这看起来像是一个静态属性或常量,用于标识模型空间。在 AutoCAD API 中,确有一个常量用于此目的,但它的访问方式通常是 BlockTableRecord.ModelSpace,并且其类型通常是 ObjectId 或一个特定的字符串常量(如 "*Model_Space")。
  • bt.[...] :这里的 [BlockTableRecord.ModelSpace] 被错误地当作了索引器的参数。索引器参数必须是表达式,而不能直接是一个类型或命名空间的成员访问路径(除非该路径最终计算出一个值)。

错误的直接原因 :编译器将 [BlockTableRecord.ModelSpace] 解析为一个特性(Attribute)应用,而不是一个索引器参数。它期望在 [] 之间找到一个特性类名或参数,但遇到了 BlockTableRecord.ModelSpace 这个成员访问表达式,这不符合特性语法,因此会报告语法错误。

3. 正确用法与修正

要正确地从 BlockTable 获取模型空间记录,需要将模型空间的标识符(通常是一个 ObjectId 或字符串)作为索引器的参数传入。以下是基于 AutoCAD .NET API 的标准做法:

csharp 复制代码
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

public void GetModelSpaceRecord()
{
    // 获取当前文档和数据库
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Database db = doc.Database;

    // 开始事务
    using (Transaction trans = db.TransactionManager.StartTransaction())
    {
        // 获取块表
        BlockTable bt = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;

        // *** 正确用法:使用索引器,传入模型空间的 ObjectId ***
        // 模型空间的 BlockTableRecord 的 ObjectId 存储在 db.BlockTableId 对应的记录中,但更常见的是通过一个常量名获取。
        // AutoCAD 提供了一个常量来获取模型空间的 ObjectId。
        ObjectId modelSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(db);

        // 方法1:使用 ObjectId 作为键(如果索引器支持)
        // 注意:标准 BlockTable 索引器通常接受字符串作为块名。但通过 ObjectId 获取记录是更常见的做法。
        // 因此,通常我们使用 GetObject 方法,而不是直接通过索引器。
        BlockTableRecord modelSpace = trans.GetObject(modelSpaceId, OpenMode.ForRead) as BlockTableRecord;

        // 方法2:使用块名作为字符串索引(如果已知)
        // 模型空间的块名通常是 "*Model_Space"
        // BlockTableRecord modelSpace = trans.GetObject(bt["*Model_Space"], OpenMode.ForRead) as BlockTableRecord;

        // ... 对 modelSpace 进行操作 ...

        trans.Commit();
    }
}

关键修正点:

  1. 移除错误的.和中括号直接组合 :不应写成 bt.[...]
  2. 使用正确的 API 获取标识符 :通过 SymbolUtilityServices.GetBlockModelSpaceId(db) 获取模型空间的 ObjectId。这是 AutoCAD API 提供的标准方法 。
  3. 通过事务获取对象 :在 AutoCAD 二次开发中,几乎所有数据库对象的访问都应在事务内进行,并使用 Transaction.GetObject() 方法,传入 ObjectId 和打开模式来获取对象的可读写引用 。

4. 其他合法场景:. 后接中括号的变体

虽然 bt.[BlockTableRecord.ModelSpace] 是错误的,但在 C# 中确实存在.后面紧跟[]的合法场景,主要与条件访问运算符数组/集合的成员访问有关:

场景 语法示例 说明
条件访问索引器 obj?.Items[0] ?. 是条件访问运算符。如果 obj 不为 null,则访问其 Items 属性的索引器 [0]。这里的 []Items(一个数组或集合)的索引器,而不是 obj 的。
链式调用中的索引器 GetData()?.Results["key"] 方法调用返回的对象,通过条件访问其 Results 属性(假设为字典),然后使用索引器 ["key"] 获取值。
访问数组的元素属性 matrix[0, 0].ToString() 访问多维数组 matrix 中特定位置的元素,然后调用该元素的 ToString 方法。这里的 [] 是数组访问,. 是访问返回元素的成员。

示例代码:

csharp 复制代码
// 条件访问示例
Dictionary<string, List<int>> data = GetData();
int? firstValue = data?.Values.FirstOrDefault()?[0]; // 安全地访问可能为null的字典和列表

// 链式调用示例
string result = service.GetResponse()?.Data["items"]?.Name;

总结

  • 核心原则 :在 C# 中,. 操作符后面直接跟 [] 的写法 obj.[...]无效语法[] 作为索引器访问,必须紧跟在对象引用或返回对象的表达式之后,中间不能有.
  • AutoCAD 特定修正 :要获取模型空间的 BlockTableRecord,应使用 SymbolUtilityServices.GetBlockModelSpaceId(db) 获取其 ObjectId,然后在事务中使用 Transaction.GetObject() 方法打开它 。
  • 合法模式 :合法的.[]的关联出现在条件访问运算符 ?. 之后,或者当[]访问返回一个对象,然后通过.访问该对象的成员时。

参考来源

相关推荐
2601_962072551 天前
李梦娇常识4600问|题库|打印版
sql·华为od·华为·c#·华为云·.net·harmonyos
m0_547486661 天前
《C#语言程序设计与实践》 全套PPT课件
c语言·c#·c语言程序设计
叶帆1 天前
【YFIOs】用C#开发硬件之设备上云
开发语言·unity·c#
IT方大同1 天前
(嵌入式操作系统)信号量
嵌入式硬件·c#
z落落1 天前
C# FileStream文件流读取文件
开发语言·c#
yngsqq1 天前
排版优化 异形排版
c#
苦学的罐头1 天前
C# 协变与逆变深度解析:为什么 IEnumerable<T> 能转换,而 List<T> 不行?
开发语言·c#·list
FuckPatience1 天前
使用ReactiveUI 前端绑定不生效
c#
天天代码码天天1 天前
用 TensorRT 加速 PP-OCR:一套 C++ DLL + C# 调用的高性能 OCR 推理方案
c++·c#·ocr