当前位置: 首页 > news >正文

C#中的CLR属性、依赖属性与附加属性

  • CLR属性的主要特征

  1. 封装性

    • 隐藏字段的实现细节

    • 提供对字段的受控访问

  2. 访问控制

    • 可单独设置get/set访问器的可见性

    • 可创建只读或只写属性

  3. 计算属性

    • 可以在getter中执行计算逻辑

    • 不需要直接对应一个字段

  4. 验证逻辑

    • 可以在setter中添加值验证

    • 可以抛出异常拒绝无效值

  5. 通知机制

    • 可以手动实现属性变更通知(如INotifyPropertyChanged)

  6. 线程安全

    • 可以添加线程同步逻辑

CLR属性的实现原理

基本实现

CLR属性本质上是编译器生成的"语法糖",编译后会转换为方法调用:

// 源代码
public class Person
{private string _name;public string Name{get { return _name; }set { _name = value; }}
}// 编译后相当于
public class Person
{private string _name;public string get_Name(){return this._name;}public void set_Name(string value){this._name = value;}
}

自动实现属性

C# 3.0引入的自动属性进一步简化了语法:

public string Name { get; set; }

编译器会自动生成一个隐藏的私有字段(通常以<Name>k__BackingField命名)和对应的get/set方法。

属性元数据

在IL(中间语言)层面,属性是通过以下元数据表示的:

  1. Property表:记录属性名称、类型和访问器方法

  2. Method表:存储get/set方法实现

  3. Field表:对于自动属性,存储编译器生成的私有字段

属性访问性能

属性访问的性能与方法调用相当,因为:

  1. 简单属性(get;set;)通常会被JIT内联优化

  2. 复杂属性(包含逻辑的)与方法调用开销相同

  3. 虚属性(virtual)会有额外的虚方法调用开销

与依赖属性的比较

特性CLR属性依赖属性
存储直接存储在对象中存储在DependencyObject的全局字典中
绑定支持需实现INotifyPropertyChanged原生支持
动画支持不支持原生支持
默认值需在构造函数设置可通过元数据指定
继承不支持支持属性值继承
内存占用每个实例都有存储只有修改过的值才占用内存
适用场景普通业务对象WPF/Silverlight/UWP控件

CLR属性的高级用法

  1. 索引器

public string this[int index] { get { /*...*/ } set { /*...*/ } }
  1. 表达式体属性(C# 6+):

public string FullName => $"{FirstName} {LastName}";
  1. 初始化器(C# 6+):

public string Name { get; set; } = "Anonymous";
  1. 只读自动属性(C# 6+):

public string Id { get; } = Guid.NewGuid().ToString();

CLR属性是C#面向对象编程的基础设施,提供了字段访问的抽象层,既能保持简洁的语法,又能提供灵活的控制逻辑。

  • 依赖属性与附加属性

依赖属性(Dependency Property)

实现原理

依赖属性是WPF/Silverlight/UWP等XAML技术中的核心概念,它扩展了传统的CLR属性,提供了更丰富的功能:

  1. 属性值继承:子元素可以继承父元素的属性值

  2. 数据绑定支持:可以直接作为数据绑定的目标

  3. 动画支持:可以被动画系统直接操作

  4. 样式支持:可以通过样式设置

  5. 元数据支持:可以指定默认值、验证回调等

  6. 值优先级系统:多个值源按照优先级决定最终值

实现依赖属性的关键是通过DependencyProperty类和DependencyObject基类:

public class MyControl : DependencyObject
{// 注册依赖属性public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register("MyProperty",                     // 属性名称typeof(string),                  // 属性类型typeof(MyControl),               // 拥有者类型new PropertyMetadata("默认值"));  // 元数据// CLR包装器public string MyProperty{get { return (string)GetValue(MyPropertyProperty); }set { SetValue(MyPropertyProperty, value); }}
}

应用场景

  1. 自定义控件开发:为自定义控件添加可绑定、可样式化的属性

  2. 数据绑定:作为数据绑定的目标属性

  3. 动画:创建可动画化的属性

  4. 模板绑定:在控件模板中使用TemplateBinding

  5. 样式设置:通过样式设置多个控件的属性值

附加属性(Attached Property)

实现原理

附加属性是一种特殊的依赖属性,它允许一个类为其他类定义属性,常用于布局系统和服务模式:

public class GridHelper
{// 注册附加属性public static readonly DependencyProperty RowCountProperty =DependencyProperty.RegisterAttached("RowCount",                     // 属性名称typeof(int),                     // 属性类型typeof(GridHelper),              // 拥有者类型new PropertyMetadata(1, OnRowCountChanged)); // 元数据// Get访问器(必须为public static)public static int GetRowCount(DependencyObject obj){return (int)obj.GetValue(RowCountProperty);}// Set访问器(必须为public static)public static void SetRowCount(DependencyObject obj, int value){obj.SetValue(RowCountProperty, value);}// 属性变更回调private static void OnRowCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){if (d is Grid grid){// 当RowCount变化时,调整Grid的行定义grid.RowDefinitions.Clear();for (int i = 0; i < (int)e.NewValue; i++){grid.RowDefinitions.Add(new RowDefinition());}}}
}

应用场景

  1. 布局系统:如Grid.Row、Grid.Column等

  2. 服务模式:如ToolTipService.ToolTip、ScrollViewer.IsScrollable等

  3. 行为扩展:为现有控件添加额外功能

  4. 自定义布局面板:创建自己的布局容器时定义布局属性

两者比较

特性依赖属性附加属性
定义方式在定义类中使用在任何类中定义,可附加到其他对象
注册方法RegisterRegisterAttached
访问器实例属性静态方法
典型用途为类定义标准属性为其他类扩展属性

高级主题

  1. 属性值优先级:本地值 > 动画 > 本地样式 > 触发器 > 隐式样式 > 样式触发器 > 模板触发器 > 样式Setter > 默认值

  2. 属性变更回调:通过PropertyMetadata指定属性变化时的处理逻辑

  3. 验证回调:通过ValidateValueCallback进行值验证

  4. 强制回调:通过CoerceValueCallback强制属性值在特定范围内

依赖属性和附加属性是WPF等XAML技术的核心机制,理解它们的原理和用法对于开发复杂的XAML应用程序至关重要。

相关文章:

  • 《零基础读懂新能源汽车》—— 新能源汽车充电革命:从逆变器原理到800V超充实战,一篇全掌握!
  • Python训练营打卡Day46(2025.6.6)
  • 【React】React 18 并发特性
  • 我爱学算法之—— 前缀和(中)
  • Spring Cloud 2025.0.0 Gateway迁移全过程详解
  • 文件上传漏洞深度解析:检测与绕过技术矩阵
  • Ubuntu创建修改 Swap 文件分区的步骤——解决嵌入式开发板编译ROS2程序卡死问题
  • 力扣100-移动0
  • 学习STC51单片机29(芯片为STC89C52RCRC)
  • 6.6 day38
  • 2025年6月6日15:48:23
  • 数字孪生:解锁未来的“数字钥匙”
  • 如何在Lyra中创建一个新的Game Feature Plugin和Experience游戏体验
  • c++中的输入输出流(标准IO,文件IO,字符串IO)
  • 从0开始学习R语言--Day18--分类变量关联性检验
  • Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
  • EM储能网关ZWS智慧储能云应用(11) — 一级架构主从架构
  • 关于事务的简介
  • 人机融合智能 | “人智交互”跨学科新领域
  • 高通camx CaptureSession
  • 用百度云服务器做网站/百家港 seo服务
  • 做做网站需要多少钱/广告公司排名
  • 铜陵app网站做招聘/优化网站
  • 中国糕点网页设计网站/售卖链接
  • 网站如何添加统计代码/天眼查询个人信息
  • 做网站的价格 外贸/武汉百度