Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >类型自定义格式字符串

类型自定义格式字符串

作者头像
张子阳
发布于 2018-09-30 02:21:09
发布于 2018-09-30 02:21:09
5850
举报

类型自定义格式字符串

2008-5-30 作者: 张子阳 分类: .Net 框架

引言

String可能是使用最多的类型,ToString()则应该是大家使用得最多的方法了。然而它不应该仅仅是用来输出类型的名称,如果使用得当,它可以方便地输出我们对类型自定义的格式。本文将循序渐进地讨论ToString(),以及相关的IFormattable、IFormatProvider以及ICustomFormatter接口。

在类型内部提供自定义格式字符串的能力

继承自System.Object 基类的 ToString()

String是人们直接就可以看懂的数据类型之一,很多情况下我们都会期望能够获得类型的一个字符串输出。因此,Microsoft 在.Net Framework所有类型的基类System.Object中提供了一个虚拟的 ToString()方法,它的默认实现是返回对象的类型名称。

假设我们有这样的一个类型,它定义了“朋友”这一对象的一些信息:

代码语言:txt
AI代码解释
复制
namespace CustomToString
   public class Friend {
       private string familyName;    // 姓
       private string firstName;     // 名

       public Friend(string familyName, string firstName){
          this.familyName = familyName;
          this.firstName = firstName;
       }    
       public Friend(): this("张","子阳"){}

       public string FamilyName {
          get { return familyName; }
       }

       public string FirstName {
          get { return firstName; }
       }
   }
}

当我们在Friend的实例上调用 ToString()方法时,便会返回类型的名称:CustomToString.Friend。

代码语言:txt
AI代码解释
复制
Friend f = new Friend();
Console.WriteLine(f.ToString()); // 输出:CustomToString.Friend

覆盖 ToString() 方法

在上面的例子中,不管类型实例(对象)所包含的数据(字段值)是什么,它总是会返回相同的结果(CustomToString.Friend)。很多时候,返回一个对象的类型名称对我们来说没有多大的意义,拿上面来说,我们可能更加期望能够返回朋友的姓名(famliyName和firstName字段的值)。这时候,我们可以简单地覆盖System.Object基类的ToString()方法,在 Friend 类中添加如下方法:

代码语言:txt
AI代码解释
复制
// 覆盖System.Object基类的 ToString() 方法
public override string ToString() {
   return String.Format("Friend: {0}{1}", familyName, firstName);
}

此时,我们再次运行代码:

代码语言:txt
AI代码解释
复制
Friend f = new Friend();
Console.WriteLine(f.ToString());    // 输出:Friend: 张子阳
f = new Friend("王","涛");
Console.WriteLine(f.ToString()); // 输出:Friend: 王涛

可以看到对于不同的对象,ToString()根据对象的字段值返回了不同的结果,这样对我们来说会更加有意义。

重载 ToString() 方法

有时候,我们可能需要将对象按照不同的方式进行格式化。就拿Friend类型来说:西方人是名在前,姓在后;而中国人是 姓在前,名在后。所以如果运行下面的代码,虽然程序不会出错,但从英语语法角度来看却有问题:

代码语言:txt
AI代码解释
复制
Friend a = new Friend("Zhang", "Jimmy");
Console.WriteLine(a.ToString());    // 输出:Friend: ZhangJimmy

而我们期望输出的是:Jimmy Zhang。这个时候,大家可以想一想想 .Net Framework 解决这个问题采用的方法:重载ToString()。让ToString()方法接收一个参数,根据这个参数来进行格式化。比如 int a = 123; Console.WriteLine(a.ToString("c"));指定了字符串"c"作为参数,产生货币类型的输出:¥123.00。我们也可以使用这种方式来改进Friend类,在Friend中重载一个 ToString() 方法,使之根据一个字符参数来定义其字符串格式化:

代码语言:txt
AI代码解释
复制
// 根据字符串参数来定义类型的格式化
public string ToString(string format) {
    switch (format.ToUpper()) {
       case "W":         // West: 西方
           return String.Format("Friend : {0} {1}", firstName, familyName);
       case "E":         // East: 东方
           return this.ToString();
       case "G":         // General 
       default:
           return base.ToString();
    }
}

然后我们在使用ToString()方法时可以使用重载的版本,对于英文名,我们传入"W"作为参数,这样就解决了上面的问题:

代码语言:txt
AI代码解释
复制
Friend f = new Friend();
Console.WriteLine(f.ToString());        // 输出:Friend: 张子阳

f = new Friend("Zhang", "Jimmy");
Console.WriteLine(f.ToString("W")); // 输出:Friend: Jimmy Zhang

这个问题更好的解决办法并非是重载ToString(),可以简单地使用属性来完成,比如这样:

代码语言:txt
AI代码解释
复制
public string WesternFullName{
    get{ return String.Format("{0} {1}", firstName, familyName)}
}
public string EasternFullName{
    get{ return String.Format("{0}{1}", familyName, firstName)}
}

在本文中,我在这里仅仅是举一个例子来说明,所以就先不去管使用属性这种方式了,后面也是一样。

实现 IFormattable 接口

我们站在类型设计者的角度来思考一下:我们为用户提供了Friend类,虽然重载的 ToString() 可以应对 东方/西方 的文化差异,但是用户的需求总是千变万化。比如说,用户是一名Web开发者,并且期望人名总是以加粗的方式显示,为了避免每次操作时都取出属性再进行格式化,他会希望只要在类型上应用ToString()就可以达到期望的效果,这样会更省事一些,比如:

代码语言:txt
AI代码解释
复制
Friend f = new Friend();
label1.Text = String.Format("<b>{0}{1}</b>", f.familyName, f.firstName);
// 这样会更加方便(用户期望):
// label1.Text = f.ToString(***);

此时我们提供的格式化方法就没有办法实现了。对于不可预见的情况,我们希望能让用户自己来决定如何进行对象的字符串格式化。Microsoft显然想到了这一问题,并为我们提供了IFormattable接口。当你作为一名类型设计者,期望为你的用户提供自定义的格式化ToString()时,可以实现这个接口。我们现在来看一下这个接口的定义:

代码语言:txt
AI代码解释
复制
public interface IFormattable {
    string ToString(string format, IFormatProvider formatProvider);
}

它仅包含一个方法 ToString():参数 format 与我们上一小节重载的ToString()方法中的 format 含义相同,用于根据参数值判断如何进行格式化;参数 formatProvider 是一个 IFormatProvider 类型,它的定义如下:

代码语言:txt
AI代码解释
复制
public interface IFormatProvider {
    object GetFormat(Type formatType);
}

其中 formatType 是当前对象的类型实例(还有一种可能是ICustomFormatter,后面有说明) --Type对象。在本例中,我们是对Friend这一类型进行格式化,那么这个formatType 的值就相当于 typeof(Friend),或者 f.GetType() (f为Friend类型的实例)。GetFormat()方法返回一个Object类型的对象,由这个对象进行格式化的实际操作,这个对象实现了 ICustomFormatter 接口,它只包含一个方法,Format():

代码语言:txt
AI代码解释
复制
public interface ICustomFormatter{
    string Format(string format, object arg, IFormatProvider formatProvider);
}

其中 format 的含义与上面相同,arg 为欲进行格式化的类型实例,在这里是Friend的一个实例,formatProvider 这里通常不会用到。

看到这里你可能会感觉有点混乱,实际上,你只要记得:作为类型设计者,你只需要实现 IFormattable 接口就可以了:先通过参数provider的 IFormatProvider.GetFormat() 方法,得到一个 ICustomFormatter 对象,再进一步调用 ICustomFormatter 对象的 Format()方法,然后返回 Format() 方法的返回值:

代码语言:txt
AI代码解释
复制
public class Friend: IFormattable{
   // 略 ...

    // 实现 IFormattable 接口
    public string ToString(string format, IFormatProvider provider) {
       if (provider != null) {
           ICustomFormatter formatter =
              provider.GetFormat(this.GetType()) as ICustomFormatter;
           if (formatter != null)
              return formatter.Format(format, this, provider);
       }

       return this.ToString(format);
    }
}

上面需要注意的地方就是 IFormatProvider.GetFormat()方法将当前的Friend对象的类型信息(通过this.GetType())传递了进去。

类型设计者的工作在这里就完结了,现在让我们看下对于这个实现了IFormattable的类型,类型的用户该如何使用自己定义的方法对对象进行字符串格式化。作为类型的用户,为了能够实现对象的自定义格式字符串,需要实现 IFormatProvider 和 ICustomFormatter接口。此时有两种策略:

  1. 建立一个类,比如叫 FriendFormatter,这个类实现 IFormatProvider 和 ICustomFormatter 接口。
  2. 建立两个类,比如叫 ObjectFormatProvider 和 FriendFormatter,分别实现 IFormatProvider 和 ICustomFormatter 接口,并且让 ObjectFormatProvider 的 GetFormat()方法返回一个 FriendFormatter 的实例。

我们先来看看第一种策略:

代码语言:txt
AI代码解释
复制
public class FriendFormatter : IFormatProvider, ICustomFormatter {
    // 实现 IFormatProvider 接口,由 Friend类的 IFormattable.ToString()方法调用
    public object GetFormat(Type formatType) {
       if (formatType == typeof(Friend))
           return this;
       else
           return null;
    }

    // 实现 ICustomFormatter 接口
    public string Format(string format, object arg, IFormatProvider formatProvider) {
       //if (arg is IFormattable)
       //  return ((IFormattable)arg).ToString(format, formatProvider);

       Friend friend = arg as Friend;
       if (friend == null)
           return arg.ToString();

       switch (format.ToUpper()) {
           case "I":
             return String.Format("Friend: <i>{0}{1}<i>" ,friend.FamilyName, friend.FirstName);
           case "B":
             return String.Format("Friend: <b>{0}{1}<b>", friend.FamilyName, friend.FirstName);
           default:
              return arg.ToString();
       }
    }
}

结合上面的 ToString()方法一起来看,这里的流程非常清楚:使用这种方式时,GetFormat中的判断语句,if(formatType == typeof(Friend)) 确保 FriendFormatter 类只能应用于 Friend类型对象的格式化。随后,通过this关键字返回了当前 FriendFormatter 对象的引用。因为FriendFormatter也实现了 ICustomFormatter接口,所以在Friend类型的 IFormattable.ToString()方法中,能够将FriendFormater 转换为一个ICustomFormatter类型,接着调用了ICustomFormatter.Format()方法,返回了预期的效果。

注意上面注释掉的部分,可能是参考了MSDN的缘故吧,有些人在实现ICustomFormatt的时候,会加上那部分语句。实际上MSND范例中使用的一个Long类型,并且使用的是String.Format()的重载方法来进行自定义格式化,与这里不尽相同。当你屏蔽掉上面的注释时,很显然会形成一个无限循环。

我们现在来对上面的代码进行一下测试:

代码语言:txt
AI代码解释
复制
public class ObjectFormatProvider : IFormatProvider {
    // 实现 IFormatProvider 接口,由 Friend类的 ToString() 方法调用
    public object GetFormat(Type formatType) {
       if (formatType == typeof(Friend))
           return new FriendFormatter();//返回一个实现了ICustomFormatter的类型实例
       else
           return null;
    }
}

// 实现ICustomFormatter接口,总是为一个特定类型(比如Friend)提供格式化服务
public class FriendFormatter : ICustomFormatter {

    // 实现 ICustomFormatter 接口
    public string Format(string format, object arg, IFormatProvider formatProvider) {
       //if (arg is IFormattable)
       //  return ((IFormattable)arg).ToString(format, formatProvider);

       Friend friend = arg as Friend;
       if (friend == null)
           return arg.ToString();

       switch (format.ToUpper()) {
           case "I":
             return String.Format("Friend: <i>{0}{1}<i>", friend.FamilyName, friend.FirstName);
           case "B":
             return String.Format("Friend: <b>{0}{1}<b>", friend.FamilyName, friend.FirstName);
           default:
              return arg.ToString();
       }
    }
}

看上去和上面的方法几乎一样,区别不过是将一个类拆成了两个。实际上,拆分成两个类会更加的灵活:使用一个类实现两个接口的方式时,FriendFormatter 只能用来格式化 Friend类型。如果再有一个Book类,类似地,需要再创建一个 BookFormatter。

而将它拆分成两个类,只需要再创建一个类实现一遍 ICustomFormatter 接口,然后对ObjectFormatProvider做些许修改就可以了。此时Provider类可以视为一个通用类,可以为多种类型提供格式化服务。现在假设我们有一个Book类型,我们只需要这样修改一下 ObjectFormatProvider类就可以了:

代码语言:txt
AI代码解释
复制
public class ObjectFormatProvider : IFormatProvider {
    // 实现 IFormatProvider 接口,由 Friend类的 ToString() 方法调用
    public object GetFormat(Type formatType) {
       if (formatType == typeof(Friend))
           return new FriendFormatter();
       if (formatType == typeof(Book))
           return new BookFormatter();  // 返回一个BookFormatter对象
       else
           return null;
    }
}
// BookFormatter 类型省略 ...

在类型外部提供自定义格式字符串的能力

现在我们站在一个类型用户的角度来思考一下:很多时候,类型的设计者并没有为类型实现IFormattable接口,此时我们该如何处理呢?我们再思考一下.Net Framework中的处理方式:

代码语言:txt
AI代码解释
复制
int a = 123;
Console.WriteLine(a.ToString("c"));        // 输出: ¥123.00
Console.WriteLine(String.Format("{0:c}", a));  // 输出: ¥123.00

实际上,String.Format()还提供了一个重载方法,可以一个接收IFormatProvider对象,这个IFormatProvider由我们自己定义,来实现我们所需要的格式化效果。根据上面的对比,我们再做一个总结:为了实现类型的自定义格式字符串,我们总是需要实现IFormatProvider接口。如果类型实现了IFormattable接口,我们可以在类型上调用ToString()方法,传递IFormatProvider对象;如果类型没有实现IFormattable接口,我们可以通过String.Format()静态方法,传递IFormatProvider对象。

现在我们就来创建实现IFormatProvider接口的类型了,与上面的方式稍稍有些不同:通过Reflector工具(不知道的可以去百度一下)可以看到,调用 String.Format() 时内部会创建一个 StringBuilder类型的对象builder,然后调用 builder.AppendFormat(provider, format, args); 在这个方法内部,最终会调用provider的GetFormat()方法:

代码语言:txt
AI代码解释
复制
formatter = (ICustomFormatter) provider.GetFormat(typeof(ICustomFormatter));

可以看到,provider.GetFormat()传递了一个typeof(ICustomFormatter)对象。因此,如果要判断是不是在类型外部通过String.Format()这种方式来使用 IFormatProvider,只需要判断 formatType是不是等于 typeof(ICustomFormatter) 就可以了:

代码语言:txt
AI代码解释
复制
public class OutFriendFormatter : IFormatProvider, ICustomFormatter
{
    // 实现 IFormatProvider 接口,由 Friend类的 ToString() 方法调用
    public object GetFormat(Type formatType)
    {
       if (formatType == typeof(ICustomFormatter))   
           return this;
       else
           return null;
    }
    
    // 实现 ICustomFormatter 略    
}

我们再次对代码进行一下测试:

代码语言:txt
AI代码解释
复制
Friend f = new Friend();
OutFriendFormatter formatter = new OutFriendFormatter();
string output = String.Format(formatter, "{0:i}", f);
Console.WriteLine(output);      // Friend: <i>张子阳<i>

.Net 中实现IFormatProvider的一个例子

.Net 中使用 IFormatProvider 最常见的一个例子就是 CultureInfo 类了。很多时候,我们需要对金额进行格式化,此时我们通常都会这样:

代码语言:txt
AI代码解释
复制
int money = 100;
Console.WriteLine(String.Format("{0:c}", money));

我们期望这个输出的结果是 ¥100.00。然而情况并非总是如此,当你将这个程序运行于中文操作系统下时,的确会如你所愿得到 ¥100.00;而在英文操作系统下,你恐怕会得到一个 $100.00。这是因为在对数字以金额方式进行显示的时候,会依据当前系统的语言环境做出判断,如果你没有显示地指定语言环境,那么就会按照默认的语言环境来进行相应的显示。在.Net中,将语言环境进行封装的类是 CultureInfo,并且它实现了IFormatProvider,当我们需要明确指定金额的显示方式时,可以借助这个类来完成:

代码语言:txt
AI代码解释
复制
int money = 100;
IFormatProvider provider = new CultureInfo("zh-cn");
Console.WriteLine(String.Format(provider, "{0:c}", money));    // 输出:¥100.00

provider = new CultureInfo("en-us");
Console.WriteLine(String.Format(provider, "{0:c}", money));    // 输出:$100.00

总结

在这篇文章中,我较系统地讨论了如何对类型进行自定义格式化。我们通过各种方式达到了这个目的:覆盖ToString()、重载ToString()、实现 IFormatProvider接口。我们还讨论了实现IFormatProvider和ICustomFormatter的两种方式:创建一个类实现它们,或者各自实现为不同的类。

我想很多人在读这篇文章以前就会使用这些方法了,我在这里希望大家能够多进行一点思考,以一个.Net 框架设计者的角度来思考:为什么会设计出三个接口配合 String.Format()静态类来实现这一过程?这样设计提供了怎样的灵活性?从这篇文章中,我期望你收获更多的不是作为一个框架使用者如何去使用这些类型,而是作为一个框架设计者来设计出这样的类型结构。

感谢阅读,希望这篇文章能给你带来帮助!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2008-5-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
编写高质量代码改善C#程序的157个建议[为类型输出格式化字符串、实现浅拷贝和深拷贝、用dynamic来优化反射]
  本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html 。本文主要学习记录以下内容:
aehyok
2018/08/31
4230
编写高质量代码改善C#程序的157个建议[为类型输出格式化字符串、实现浅拷贝和深拷贝、用dynamic来优化反射]
[C#]使用IFormattable接口来实现字符串格式化
本文介绍了一种C#字符串格式化方法,通过自定义格式化方式和格式化参数,实现对字符串的个性化格式化。具体实现包括定义一个格式化类,一个继承IFormattable的类,以及一个Person类。格式化类提供格式化方法,接受格式化参数,并提供获取格式化方式的方法。IFormattable接口提供ToString方法,用于格式化输出。在主函数中,定义一个Person对象并调用其ToString方法,输出格式化后的字符串。
CNXY
2017/12/25
7570
[C#]使用IFormattable接口来实现字符串格式化
浅谈.Net Framework中string.Format原理
运行结果:Hello, I am nestor, today is 2019-07-08.
小蜜蜂
2019/07/15
8420
C# 自定义类型通过实现IFormattable接口,来输出指定的格式和语言文化的字符串(例:DateTime)
在开发一些国际化的应用时,应用程序需要调用与当前线程不同的语言文化来格式化字符串.
郑小超.
2018/08/01
1.1K0
C# 自定义类型通过实现IFormattable接口,来输出指定的格式和语言文化的字符串(例:DateTime)
C# 温故而知新:Stream篇(三)
TextWriter 和 StreamWriter 目录: 为何介绍TextWriter? TextWriter的构造,常用属性和方法 IFormatProvider的简单介绍 如何理解StreamW
逸鹏
2018/04/10
1.1K0
C# 温故而知新:Stream篇(三)
.NET6新东西--插值字符串优化
字符串是我们平时使用最多的一个类型,从C#6开始就支持插值字符串,方便我们进行字符串的操作,并且大部分分析器也推荐使用插值这种写法,因为它够使得我们的代码更加清晰简洁,到了.NET6中的C#10则为我们提供了更好的实现方式以及更佳的性能。 那么什么是插值字符串呢?它是以符开头的,类似于 “Hello {name}” 这样的字符串,下面的例子是插值字符串的简单使用:
喵叔
2021/11/26
1.3K0
浅谈StreamWriter类
之前的文章介绍了StreamReader类,本文主要介绍StreamWriter类,我们先看一下StreamWriter的定义:
小蜜蜂
2019/07/15
6570
浅谈StreamWriter类
运算符重载,以及迭代器[foreach]示例
 以下代码来源于"c#高级编程(第4版)",只不过我对它做了一些注释和修改 using System; using System.Collections; using System.Text; namespace Wrox.ProCSharp.VectorAsCollection {     class MainEntryPoint     {         static void Main(string[] args)         {             Vector Vect
菩提树下的杨过
2018/01/22
6520
聊聊字符串拼接的哪一些事儿
​ 字符串对我编程人员来说是字符串时每天见面的常客,你不认识不熟悉他都不得行,字符串的拼接更是家常便饭,那么在实际开发过程中实现字符串的拼接有哪一些方式呢?咱们一起来聊聊,来交流沟通,学习一波。也许你会说,那也太简单了嘛,谁不会啊,哈哈,使用起来确实简单,但是不一定我们都使用的方式还有优秀的方式吗?
小小许
2020/01/15
5630
聊聊字符串拼接的哪一些事儿
[深入解析C#] 泛型
使用泛型(generic),可以编写在编译时类型安全的通用代码,无须事先知道要使用的具体类型,即可在不同位置表示相同类型。在引入之初,泛型主要用于集合。如今,泛型已经广泛应用于C#的各个领域,其中用得较多的有如下几项:
科控物联
2022/03/29
1.6K0
[深入解析C#] 泛型
.Net Remoting(分离服务程序实现) - Part.3
在上面Remoting基本操作的范例中,我们发现了这样一个情况:即是 客户应用程序 仍然需要引用 服务程序集(ServerAssembly),因为它需要DemoClass的元信息来创建代理。使用这种共享服务程序集的方式构建Remoting程序,其运行时的示意图如下所示:
张子阳
2018/09/30
4780
.Net Remoting(分离服务程序实现) - Part.3
C# String.Format的格式限定符与Format方法将多个对象格式化一个字符串原理
Format方法将多个对象格式化成一个字符串Format方法解析格式字符串的原理:
郑小超.
2018/08/01
5.6K0
C# String.Format的格式限定符与Format方法将多个对象格式化一个字符串原理
C# 字符串操作详解
作用:判断传入的字符串是不是当前字符串的开头,可设置比较类型(二进制比较、忽略语言文化比较、按当前线程的语言文化比较)
郑小超.
2018/08/01
1.6K0
C# 字符串操作详解
字符串插值_让我们帮助QueryProvider处理插值字符串
QueryProvider的细节 (Specifics of QueryProvider)
用户7886150
2021/01/14
7630
通过自定义配置实现插件式设计
软件设计有一句话叫做“约定优于配置”,很多人将其作为拒绝配置的理由。但是,“约定”和“配置”的使用,都有个度的问题。我不赞为了所谓的扩展性,为你的应用设计一套只有你自己才能看懂的配置体系。但是,在很多场景中,配置是提供应用灵活度的首要甚至是唯一途径。对于框架的设计者来说,对于配置的驾驭是一项基本的技能。 可能你很少使用自定义配置,可能你理解的自定义配置仅仅限于AppSetting,不过我想你应该对于System.Configuration这个命名空间下的几个基本的类型有基本的了解。比如Configurati
蒋金楠
2018/02/07
7710
枚举的多语言显示
关于枚举类型的多语言显示,其实就是Globalization的问题。解决方案当然不止一种,这里介绍一种可用性和扩展性的比较好的通用方法。 显然这里自己去实现自定义格式化,即通过IFormatable、IFormatProvider、ICustomFormatter等接口已达到Globalization有点小题大作了,而另外一个很容易想到的点是通过DiaplayMember实现显示值得自定义(对于简单Binding,例如ComboBox、ListBox等只用重载ToString就可以了)。 首先,我们希望Bi
葡萄城控件
2018/01/10
1.3K0
让IoC动态解析自定义配置(提供基于Unity的实现)
在《通过自定义配置实现插件式设计》中,通过在运行时对配置的动态解析实现了真正的“插件式”设计,其本质就是让配置自行提供对配置类型实例的创建。在这篇文章中,我们将更进一步,让自定义配置和IoC集成起来。IoC的目的就是通过解析注册的依赖注入信息,最终创建出我们希望的某个对象。而只有通过配置的方式来定义IoC容器需要的注入信息,才能实现灵活的设计。所以,如果将两者集成起来,让IoC容器能够解析通过配置定义的“依赖注入”信息,具有很大的现实意义。接下来,我们将通过Unity为例,介绍IoC和自定义进行无缝集成的实
蒋金楠
2018/02/07
9900
浅谈C#数组(一)
  如果需要使用同一类型的多个对象,可以使用数组和集合(后面介绍)。C#用特殊的记号声明,初始化和使用数组。Array类在后台发挥作用,它为数组中的元素排序和过滤提供了多个方法。使用枚举器,可以迭代数组中的所有元素。   如果需要使用不同类型的多个对象,可以使用Tuple(元组)类型。
全栈程序员站长
2022/09/07
9610
浅谈C#数组(一)
字符、字符串和文本的处理之Char类型
.Net Framework中处理字符和字符串的主要有以下这么几个类: (1)、System.Char类 一基础字符串处理类 (2)、System.String类 一处理不可变的字符串(一经创建,字符
郑小超.
2018/05/28
1.2K0
C#之反射、元数据详解
  在本节中主要讲述自定义特性、反射。自定义特性允许把自定义元数据与程序元素关联起来。这些元数据是在编译过程中创建的,并嵌入程序集中。反射是一个普通的术语,它描述了在运行过程中检查和处理程序元素的功能。例如,反射运行完成以下任务:
小世界的野孩子
2019/09/11
1.5K0
推荐阅读
相关推荐
编写高质量代码改善C#程序的157个建议[为类型输出格式化字符串、实现浅拷贝和深拷贝、用dynamic来优化反射]
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文