浅析System.Console.WriteLine()

Writeline()函数的功能向 StreamWriter 类写入指定字符串和一行字符,共有19个重载,其与Write()函数的主要区别在于它输出字符串后换行,而Write()不换行。现在,通过WriteLine()的通用版本(即WriteLine(string format,object arg0,object arg1,object arg2,object arg3,__arglist))来深入理解其实现细节。

首先,我们来看一下源代码:

[CLSCompliant(false), HostProtection(SecurityAction.LinkDemand, UI=true)

public static void WriteLine(string format, object arg0, object arg1, object arg2, object arg3, __arglist)

{

ArgIterator iterator = new ArgIterator(__arglist);

int num = iterator.GetRemainingCount() + 4;  //参数个数

object[] arg = new object[num];    //参数集合

arg[0] = arg0;

arg[1] = arg1;

arg[2] = arg2;

arg[3] = arg3;

for (int i = 4; i < num; i++)

{

arg[i] = TypedReference.ToObject(iterator.GetNextArg());

}

Out.WriteLine(format, arg);

}

看函数签名可知,WriteLine()是一个静态的无返回值的有可变参数的函数。并通过TextWrite的一个静态对象(Out)的方法(Out.WriteLine())输出字符串。

(注:TextWrite是一个抽象类,无法实例化,所以Out实际上是StreamWrite类的一个实例的引用)

[__DynamicallyInvokable]

public virtual void WriteLine(string format, params object[] arg)

{

this.WriteLine(string.Format(this.FormatProvider, format, arg));

}

代码很简短,就是调用同一个对象的WriteLine() 的另一个重载,并使用String类的一个方法用参数替换字符串中相应的占位符,得到要输出的完整的字符串。

[__DynamicallyInvokable]

public virtual void WriteLine(string value)

{

if (value == null)

{

this.WriteLine();

}

else

{

int length = value.Length;

int num2 = this.CoreNewLine.Length;  //CoreNewLine默认值为"\r\n"

char[] destination = new char[length + num2];  //包含换行符的字符串(目的字符串)

value.CopyTo(0, destination, 0, length);

switch (num2)  //确定CoreNewLine的值是 "\n"(num2==1) 还是 "\r\n"(num2==2)

{

case 2:

destination[length] = this.CoreNewLine[0];

destination[length + 1] = this.CoreNewLine[1];

break;

case 1:

destination[length] = this.CoreNewLine[0];

break;

default:

Buffer.InternalBlockCopy(this.CoreNewLine, 0, destination, length * 2, num2 * 2);

break;

}

this.Write(destination, 0, length + num2);

}

}

处理换行符并添加到字符串中,用Write()的一个重载输出。

 

[__DynamicallyInvokable]

public virtual void Write(char[] buffer, int index, int count)

{

if (buffer == null)

{

throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));

}

if (index < 0)

{

throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));

}

if (count < 0)

{

throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));

}

if ((buffer.Length - index) < count)

{

throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));

}

for (int i = 0; i < count; i++)

{

this.Write(buffer[index + i]);

}

}

从第一个字符开始检查字符串是否有异常,只有完全没异常后才调用Write()将最终的字符串输出(一个字符一个字符的输出)。

[__DynamicallyInvokable]
public override void Write(char value)
{
    this.CheckAsyncTaskInProgress();  //异步操作
    if (this.charPos == this.charLen)
    {
        this.Flush(false, false);
    }
    this.charBuffer[this.charPos] = value;
    this.charPos++;
    if (this.autoFlush)
    {
        this.Flush(true, false);
    }
}
注:TextWriter 类并没有实现此方法,Out对象调用的是StreamWriter 的一个实例,而 StreamWriter 继承自 TextWriter 并实现了此方法。

System.Console.WriteLine()的功能是输出一个字符或字符串并换行,其实现考虑到了各个方面,包括功能的细化,精密的组织,鲜明的层次等。

我们编程,不一定要向别人这样将一个类,一个方法写的这样有条理,但应当学习别人的编程的思想与代码的结构与组织方法等,并尽量向别人看齐,

这样,有助于我们在编程的时候构建一个清晰的代码体系和结构,提高编程效率与学习效率。

浅析System.Console.WriteLine()的更多相关文章

  1. System.Console.WriteLine() 调用原理

    1.System.Console.WriteLine(类的实例)默认调用类的Tostring()方法.如果自定义的新类未override ToString()方法.那么调用Object.ToStrin ...

  2. VS2015使用技巧 为什么我们可以输入cw后按两下tab键出现console.writeline

    镇场诗: 大梦谁觉,水月中建博客.百千磨难,才知世事无常. 今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ 为什么 ...

  3. C# Winform里面用Console.WriteLine输出到哪了

    C# Winform里面用Console.WriteLine输出也不会报错 显示在 VS IDE 的视图→输出窗口,且只在 Debug 环境下此语句执行. 如果是 Release 环境,在 Win32 ...

  4. C#核编之System.Console类

    顾名思义,Console类封装了基于控制台的输入输出和错误流的操作,下面列举一些System.Console类常用的成员的,这些成员能为简单的命令行程序添加一些"情趣",例如改变背 ...

  5. 第一个输出程序 Console.WriteLine

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. C#中Console.WriteLine()函数输出格式详解

    格式项都采用如下形式: {index[,alignment][:formatString]} 其中"index"指索引占位符,这个肯定都知道: ",alignment&q ...

  7. 看到Console.WriteLine($"string")写法,一时间不理解$的用途

    参了网上资料,原来它是C# 6.0的语法糖. C# 6.0 新加上的功能:   Null-Conditional Operator 大概就是,简洁代码量,缩短一些关于为null的判断~ 旧写法: pu ...

  8. c# System.Console

    System.Console类公开了和操作控制台相关的有用的静态字段和静态方法.下面是System.Console中一些较为重要的方法. public static void Beep()该方法播放蜂 ...

  9. C#里面Console.Write()和Console.WriteLine()有什么区别?

    Console.Write()和Console.WriteLine()都是System.Console提供的方法,两着主要用来将输出流由指定的输出装置(默认为屏幕)显示出来.两着间的差异在Consol ...

随机推荐

  1. 元素(Element)和结点(Node)的区别(org.w3c.dom)

    1.元素(Element)和结点(Node)的区别, 元素是一个小范围的定义,必须是含有完整信息的结点才是一个元素,例如 - . 但是一个结点不一定是一个元素,而一个元素一定是一个结点. 什么是nod ...

  2. 菜鸟攻城狮2(JAVA开发环境)

    1.JDK下载路径:www.oracle.com/technetwork/java/javase/downloads 2.安装案例:最后一步认证操作 win+R 或者 点击开始--〉运行 输入“cmd ...

  3. free查看内存情况

    free命令可以显示当前系统未使用的和已使用的内存数目,还可以显示被内核使用的内存缓冲区. free [option]     -b:以Byte为单位显示内存使用情况:      -k:以KB为单位显 ...

  4. mongodb教程国外

    https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/

  5. 树莓派 Learning 002 装机后的必要操作 --- 04 添加软件源 之 添加公钥 --- 解决“由于没有公钥,无法验证下列签名”问题

    树莓派 装机后的必要操作 - 添加软件源 解决 添加公钥 时会遇到的问题 当你添加完Debian的软件源后,在终端中执行sudo apt-get update时,会出现下面的错误:(这里我添加了3个软 ...

  6. Hadoop添加节点datanode(生产环境)

    Hadoop添加节点datanode 博客分类: hadoop HadoopSSHJDKXML工作  1.部署hadoop    和普通的datanode一样.安装jdk,ssh  2.修改host  ...

  7. wpf listboxitem添加下划线

    1.通过List<string>进行赋值,没有字段绑定 // 前台xaml <ListBox x:Name="list1"> <ListBox.Ite ...

  8. 项目:IT资源共享资源(登录后端)<2>

    公众号技术标签 小程序 PHP 源码 项目 ThinkPHP5.0目录结构,新建一个模块api,该模块下面有controller.model 目录,前者放控制器,写API接口(这里是简单的api写法) ...

  9. [CentOS7] at, bash, cron, anacron

    声明:本文主要总结自:鸟哥的Linux私房菜-第十五章.例行性工作排程(crontab),如有侵权,请通知博主 at => /var/spool/at /etc/at.allow, /etc/a ...

  10. Zabbix监控系统配置之-自动发现规则入门

    假设你已经知道[模板-监控项-监控项原型-自动发现规则]之间的关系.(此处应有关系图,待填坑) 1. 添加模板 我新建了一个名叫Dapianzi SNMP Linux的模板,里面添加了已经启动了SNM ...