简单的System.IFormattable实现示例:

本文介绍如何通过实现System.IFormattable接口来格式化自定义类型的输出。通过C#示例展示了如何根据不同格式化字符串呈现不同形式的数据展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现System.IFormattable接口可以使用string.Format()方法按照不同的方式格式化自定义的类型,其实在使用Console.WriteLine("Cubic1: {0,15:XYZ}",a);方法,也只是先把Cubic1: {0,15:XYZ}字符串传递给string.Format()方法,格式化完毕后,送到控制台输出。

class Class1

        {

                static void Main(string[] args)

                {

            Cubic a = new Cubic(10,24,52);

//使用XYZ格式化字符串

            Console.WriteLine("Cubic1: {0,15:XYZ}",a);

//使用16X格式化字符串

            Console.WriteLine("Cubic1: {0,25:16X}",a);

//使用默认格式化字符串

            Console.WriteLine("Cubic1: {0,15}",a);

//使用非法格式化字符串,其实还是默认格式化字符串

            Console.WriteLine("Cubic1: {0,15:654}",a);

                }

        }

 

    struct Cubic:System.IFormattable

    {

        int x,y,z;

 

        public Cubic(int x,int y,int z)

        {

            this.z = z;

            this.x = x;

            this.y = y;

        }

//这个方法是要实现System.IFormattable所必需的format就是格式化字符串

        public string ToString(string format, IFormatProvider formatPorvider)

        {

            if(format == null)

                return ToString();

            switch( format )

            {

                case "XYZ":

                    return "X="+x.ToString()+" Y="+y.ToString()+" Z="+z.ToString();

                case "16X":

                    return string.Format("x={0,-5:X},y={1,-5:X},z={2,-5:X}",x,y,z);

                default:

                    return ToString();

            }

        }

 

        public override string ToString()

        {

            return "( " + x.ToString() + " , " +y.ToString()+ " , " + z.ToString() + " )";

        }

    }

 

输出结果如下:

Cubic1:  X=10 Y=24 Z=52

Cubic1:   x=A    ,y=18   ,z=34  

Cubic1: ( 10 , 24 , 52 )

Cubic1: ( 10 , 24 , 52 )

<think>我们正在讨论C#中接口的定义和实现。根据引用内容,接口是一种特殊的类型,它定义了一组方法、属性、事件和索引器的签名,但不提供具体实现。类或结构通过实现接口来提供这些成员的具体实现。 定义接口的语法: 使用`interface`关键字,接口名称通常以大写字母I开头(例如`IExample`)。接口中的成员默认是公共的,且不能包含访问修饰符(如public),因为接口成员默认就是公开的。 实现接口的类必须提供接口中所有成员的具体实现。 有两种实现方式:隐式实现和显式实现。 - 隐式实现:直接在类中定义与接口成员签名相同的方法(或属性等),并且使用public修饰符。这样,这些成员可以通过类的实例直接访问,也可以通过接口的实例访问。 - 显式实现:在类中定义接口成员时,使用接口名称作为前缀(例如`void IExample.Method()`),并且不能使用访问修饰符。显式实现的成员只能通过接口类型的引用来访问,不能通过类实例直接访问。 下面我们通过一个完整的例子来展示如何定义接口并实现接口方法。 步骤: 1. 定义接口(例如`IMyInterface`),包含一个方法`DoSomething`和一个属性`MyProperty`。 2. 创建一个类(例如`MyClass`)来实现这个接口。 3. 在类中,我们可以隐式实现或显式实现接口成员。 示例代码: ```csharp // 定义接口 public interface IMyInterface { // 方法声明 void DoSomething(); // 属性声明 int MyProperty { get; set; } } // 实现接口的类(隐式实现) public class MyClass : IMyInterface { // 隐式实现属性 public int MyProperty { get; set; } // 隐式实现方法 public void DoSomething() { Console.WriteLine("MyClass is doing something!"); } } // 显式实现接口的例子 public class MyClassExplicit : IMyInterface { // 显式实现属性:使用接口名称.属性名 int IMyInterface.MyProperty { get; set; } // 显式实现方法:使用接口名称.方法名 void IMyInterface.DoSomething() { Console.WriteLine("MyClassExplicit is doing something (explicit implementation)."); } // 注意:显式实现的成员不能通过类实例访问,只能通过接口实例访问 } class Program { static void Main() { // 隐式实现接口的调用 MyClass myObj = new MyClass(); myObj.DoSomething(); // 直接通过类实例调用 myObj.MyProperty = 10; // 通过接口引用调用 IMyInterface myInterface = myObj; myInterface.DoSomething(); // 显式实现接口的调用 MyClassExplicit explicitObj = new MyClassExplicit(); // 不能这样调用:explicitObj.DoSomething(); 因为显式实现的成员不是类公共接口的一部分 IMyInterface explicitInterface = explicitObj; // 转换为接口类型 explicitInterface.DoSomething(); // 通过接口调用 explicitInterface.MyProperty = 20; // 通过接口设置属性 } } ``` 说明: 1. 在隐式实现中,类`MyClass`直接提供了接口成员的公共实现,因此可以通过类的实例直接调用。 2. 在显式实现中,类`MyClassExplicit`将接口成员实现为显式,这些成员只能通过接口类型的变量来访问。这样可以避免类公共接口的成员过多,或者解决多个接口有相同成员名称时的冲突问题。 另外,引用[4]中提到了`IFormattable`接口,这是一个系统定义的接口,用于支持自定义格式化字符串。我们可以通过实现该接口来定义对象如何格式化为字符串。这进一步说明了接口的实际应用。 相关问题: 1. 接口和抽象类有什么区别? 2. 如何实现多个接口? 3. 显式接口实现有什么应用场景? 4. 如何在接口中定义事件和索引器?</think>### C# 接口定义与实现指南 接口(Interface)是 C# 中的特殊类型,定义了一组方法、属性、事件和索引器的**签名规范**,但不提供具体实现。类通过实现接口来遵守这些规范,实现代码解耦和多态性[^2][^3]。 --- #### 一、接口定义语法 ```csharp public interface IMyInterface { // 方法声明(无实现) void DoWork(); // 属性声明 int Priority { get; set; } // 事件声明 event EventHandler WorkCompleted; // 索引器声明 string this[int index] { get; set; } } ``` **核心特点**: 1. 使用 `interface` 关键字声明 2. 命名以大写字母 `I` 开头(如 `IComparable`) 3. 只能包含成员签名,不能有实现代码 4. 默认成员访问级别为 `public`(不能添加显式访问修饰符) --- #### 二、接口实现方式 ##### 1. 隐式实现(常用) ```csharp public class Worker : IMyInterface { // 实现接口方法 public void DoWork() { Console.WriteLine("Working..."); } // 实现接口属性 public int Priority { get; set; } // 实现接口事件 public event EventHandler WorkCompleted; // 触发事件的方法 public void CompleteWork() { WorkCompleted?.Invoke(this, EventArgs.Empty); } } ``` ##### 2. 显式实现(解决命名冲突) ```csharp public class SpecialWorker : IMyInterface { // 显式实现(无访问修饰符) void IMyInterface.DoWork() { Console.WriteLine("Special work"); } // 使用方式 var worker = new SpecialWorker(); ((IMyInterface)worker).DoWork(); // 必须通过接口引用调用 } ``` --- #### 三、接口使用示例 ```csharp // 定义日志接口 public interface ILogger { void Log(string message, LogLevel level); } public enum LogLevel { Info, Warning, Error } // 实现控制台日志 public class ConsoleLogger : ILogger { public void Log(string message, LogLevel level) { Console.WriteLine($"[{level}] {DateTime.Now}: {message}"); } } // 使用接口 class Program { static void Main() { ILogger logger = new ConsoleLogger(); logger.Log("System started", LogLevel.Info); // 切换实现(文件日志) logger = new FileLogger(); // 假设已实现 logger.Log("Data saved", LogLevel.Info); } } ``` --- #### 四、高级用法 ##### 1. 实现系统接口(如 IFormattable) ```csharp public class Vector : IFormattable { public double X, Y, Z; // 实现自定义格式化 public string ToString(string format, IFormatProvider formatProvider) { return format switch { "IJK" => $"{X}i + {Y}j + {Z}k", "VE" => $"{X:E2},{Y:E2},{Z:E2}", _ => $"({X}, {Y}, {Z})" }; } } // 使用 Vector v = new Vector { X=1.2, Y=3.4, Z=5.6 }; Console.WriteLine(v.ToString("IJK", null)); // 输出: 1.2i + 3.4j + 5.6k ``` ##### 2. 多接口实现 ```csharp public class SmartDevice : IConnectable, IUpdatable { // 实现IConnectable public void Connect() { ... } // 实现IUpdatable public void UpdateFirmware() { ... } } ``` --- #### 五、接口设计最佳实践 1. **单一职责原则**:每个接口聚焦单一功能 2. **命名清晰**:使用 `I+动词` 命名(如 `ISortable`) 3. **避免臃肿**:接口成员不超过 5-7 个 4. **依赖倒置**:高层模块依赖抽象接口而非具体实现 5. **接口组合**:通过继承创建复合接口 ```csharp public interface IAdvancedLogger : ILogger, IErrorTracker { void ExportLogs(); } ``` --- ### 常见问题解决 **Q: 如何判断类是否实现接口?** ```csharp var obj = new Worker(); if(obj is IMyInterface) { // 安全调用接口方法 } ``` **Q: 接口与抽象类的区别?** | 特性 | 接口 | 抽象类 | |--------------|--------------------------|----------------------| | 实现 | 多继承 | 单继承 | | 成员类型 | 方法/属性/事件/索引器 | 可包含字段和实现方法 | | 访问修饰符 | 隐式public | 支持各种访问修饰符 | | 版本控制 | 添加新成员会破坏现有实现 | 可添加新虚方法 | --- ### 完整示例 ```csharp // 定义接口 public interface IShape { double Area { get; } double Perimeter { get; } void Draw(); } // 实现接口 public class Circle : IShape { public double Radius { get; set; } public double Area => Math.PI * Radius * Radius; public double Perimeter => 2 * Math.PI * Radius; public void Draw() { Console.WriteLine($"Drawing circle (R={Radius})"); } } // 使用 IShape shape = new Circle { Radius = 5 }; Console.WriteLine($"Area: {shape.Area:F2}"); // 输出: Area: 78.54 shape.Draw(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值