c#最佳实践和技巧

Share

本资源包含c#的最佳实践和技巧的集合, provided by our Toptal network members.

这个资源包含了由我们的Toptal网络成员提供的c#最佳实践和c#技巧的集合. As such, 本页将定期更新,以包括其他信息和涵盖新兴技术. This is a community driven project, 所以我们也鼓励你们做出贡献, and we are counting on your feedback.

C# is a general-purpose, multi-paradigm, 由微软公司开发的面向对象程序设计语言, 主要用于在分布式环境中开发软件组件. c#在设计上强调可移植性、软件健壮性和国际化.

Check out the Toptal resource pages for additional information on C#. There is a C# hiring guide, C# job description, common C# mistakes, and C# interview questions.

如何使用响应式快速处理文本文件 .NET?

处理文本文件是我们作为程序员都做过的事情. However, 操作大型(多gb)文件引发了一个问题:如何才能尽快完成操作, 并且不需要将整个文件加载到内存中?

文本文件通常有一个头(一到几行),后面跟着一些数据行. 处理该文件将生成另一个文本文件, 每个输入行产生一个或多个输出行.

在这篇简短的文章中,我将解释如何使用 Rx.NET library. The entire example project is available at Bitbucket. Here is how to solve this task.

首先,从URL加载文件并返回 IObservable,每个字符串是一个单独的行. 我将其分成以下几类:

The WebLoader 类负责打开资源(本地或远程文件)并将其作为流返回. 我提取它作为一个单独的类,而不是仅仅使用 Open method in the RemoteTextLoader,因为我希望能够编写自包含的单元测试,而不需要访问网络.

The RemoteTextLoader 类将接受该流并将其作为string的可观察对象返回, with each string being a separate line. You can see the main code below; loader is an instance of the WebLoader class, and the ReadLoop method simply returns one line at a time.

        public IObservable Read(string url)
        {
            return Observable.Using(
                () => new StreamReader(loader.Open(url)),
                sr => ReadLoop(sr).ToObservable(scheduler));
        }

The RemoteTextLoader.Read method ensures that the StreamReader 它的底层流在可观察对象完成操作后关闭 Observable.Using call. 这对于防止资源泄漏非常重要. The call to the private ReadLoop method will run on the given scheduler; we don’t want to block the calling thread.

Finally, the WebStream 类不仅负责关闭输入流,还负责关闭web请求, also to prevent leaking resources.

Then, 在将输入文件转换为(响应的)行流之后, 该流必须被分割成几个流,每个流在不同的线程上并行处理.

The ProducerConsumerSplitter class handles the first part; its Split 方法接受一个输入可观察对象和一个计数,并返回一个可观察对象数组.

    public class ProducerConsumerSplitter : Splitter
    {
        public IObservable[] Split(IObservable observable, int count)
        {
            //如果集合增长超过(线程数* 10)项,阻塞
            var collection = new BlockingCollection(count * 10);

            observable.Subscribe(collection.Add, () => collection.CompleteAdding());

            return Enumerable
                .Range(0, count)
                .Select(_ => CreateConsumer(collection))
                .ToArray();
        }

        //

        private static IObservable CreateConsumer(BlockingCollection collection)
        {
            return Observable.Create(o =>
            {
                while (!collection.IsCompleted)
                {
                    T item;
                    if (collection.TryTake(out item))
                        o.OnNext(item);
                }
                o.OnCompleted();

                return Disposable.Empty;
            });
        }
    }

拆分器使用生产者-消费者模式将一个可观察对象拆分为多个. 生产者部分订阅了输入可观察对象,并开始将其项目添加到集合中, 如果项的数量大于任意选择的输出可观察对象数量的十倍的限制,则阻塞. This way, 消费者可观察对象并不缺乏需要处理的项目, 我们也不会用多gb的输入文件填满内存.

消费者只需从集合中读取项,直到 IsCompleted returns true,当集合为空时发生 and 没有更多的项目等待添加到它. Note that you should not use the IsAddingCompleted method here since it gets set to true 一旦生产者完成向集合中添加项目, 即使仍有项目需要处理.

线程上的实际处理在 ParallelProcessor 类,它将加载和拆分委托给前面的类,然后调用 LineProcessor 将每个输入行转换成一个或多个输出行.

        public IObservable Process(string url, int headerSize, LineProcessor lineProcessor)
        {
            var lines = loader.Read(url);

            //需要在这里使用Publish,否则流将被枚举两次
            return lines.Publish(shared =>
            {
                var header = shared.Take(headerSize).ToArray();
                var rest = shared.Skip(headerSize);

                var streams = splitter.Split(rest, ThreadCount);

                //使用SubscribeOn而不是ObserveOn,因为处理在订阅时立即开始
                return header
                    .SelectMany(h => streams
                        .Select(stream => ProcessLines(stream, h, lineProcessor)
                            .SubscribeOn(scheduler)))
                    .Merge();
            });
        }

这个类负责加载文件, 处理每一行(根据请求使用尽可能多的线程),然后将结果合并到单个可观察对象中.

最后,主程序将结果写入 output.txt 文件,还度量处理整个文件所花费的时间. 测试程序所做的处理相当简单, so no doubt the real code would be slower, 但我的机器每秒处理的行数接近100万行, which is encouraging.

Contributors

Marcel Popescu

Freelance C# Developer

Romania

Marcel是一名拥有20多年经验的高级开发人员. 他更喜欢后端开发,擅长算法,并为自己设计良好的代码而自豪. 他写了一本关于TDD的介绍性书籍,目前正在指导几个初级程序员.

Show More

从Toptal获取最新的开发人员更新.

Subscription implies consent to our privacy policy

Know The Libraries

While the .NET Framework Class Library (FCL) 为大多数场景提供各种各样的类, 它的第三方图书馆生态系统近年来蓬勃发展,解决了一些不足之处,其中许多值得了解. Here, we will cover some of the most useful, popular, and more importantly, open source thus consequently free, 第三方库,帮助您选择最适合您需要的库.

Json.NET

As the name suggests Json.NET is a library for working with JSON, 提供在JSON和JSON之间进行序列化和反序列化的方法 .NET objects. It is highly customizable, 允许您指定JSON应该如何格式化, how to handle dates, 属性名称应该如何大写, and so on. Json.NET is available as Portable Class Library, making也适用于Xamarin和Windows Phone项目.

Dapper

Created by StackExchange, Dapper 是一个轻量级的对象映射器,与任何具有ADO的数据库兼容.NET provider. Simply, it executes a query and maps results to your classes; it does not generate database queries or model classes for you. 是什么让Dapper从其他类似的库中脱颖而出? Speed. Dapper比实体框架快得多,只比原始ADO慢一点点.NET.

NLog

详细的日志记录不仅允许您监视应用程序性能,而且也是诊断生产中的问题的关键. NLog 附带了数十个布局渲染器,它们以声明的方式向每个日志消息添加上下文信息. NLog也是可扩展的,允许您创建自定义日志目标或自定义布局渲染器. 配置选项允许您记录到文件系统, directly to a database, track an event log, plus logging via email.

Topshelf

Topshelf 在创建了普通的控制台应用程序之后,通过处理所有幕后细节,使编写Windows服务变得轻而易举. 没有必要担心从 ServiceBase class or needing to add a ProjectInstaller/ServiceProcessInstaller; merely, 告诉Topshelf您的服务应该命名为什么,以及在服务启动和停止时Topshelf应该调用哪些方法, 您将得到一个控制台应用程序,您可以调试它,而无需经历所有通常的困难.

Hangfire

Hangfire 是一个库,允许您在ASP中添加不同类型的后台作业.NET projects. 它支持各种后台任务类型,如“即发即弃”, delayed, and recurring, without needing a separate Windows Service. It includes a beautiful, 光滑的仪表板,让您可以快速获得所有工作的概述, running or failed. 该库还将同步不同机器上的作业.

AutoFixture

By using AutoFixture 对于单元测试,在任何给定的测试中都不需要外设依赖项的mock. AutoFixture“自动神奇地”创建匿名变量和被测系统的实例(SUT). 因此,向SUT的构造函数添加新参数不会中断任何测试. 如果您将AutoFixture与其他单元测试框架集成, 您将收到一个SUT实例和其他变量作为测试参数, minimizing your test code even further.

Humanizer

需要将Pascal大小写字符串转换为可读的句子? Need to pluralize or singularize words? Convert numbers to words? 日期为相对日期或时间跨度为友好字符串? The Humanizer 库“人性化”您的数据,支持英语和近四十种其他人类语言.

AngleSharp

AngleSharp 是一个用于解析和操作HTML文档的库. 它完全支持HTML5,就像浏览器一样,它可以处理格式错误的HTML. After parsing the HTML, it provides a DOM, 你可以用CSS选择器或LINQ过滤器来查询. The DOM is fully interactive, 因此,您可以删除或添加新元素,DOM将反映更改. AngleSharp是一个可移植类库, 使其可用于Xamarin和Windows Phone项目.

ImageProcessor

如果你需要在应用中操作图像, ImageProcessor is your new best friend; it can resize, rotate, watermark, crop, apply various filters, and more, plus, it does so in a very efficient way. ImageProcessor流畅的接口使得探索API很容易,而且它的库不依赖于GDI+, so it also works on the .NET Core too.

VerbalExpressions

正则表达式(也称为RegEx)功能强大,但很难编写, read and maintain in general. This is what VerbalExpressions tries to solve; it comes with a descriptive, 流畅的API,结果更具表现力, easy to follow code. 考虑一下这个丑陋的RegEx代码来检查字符串是否是一个有效的url:

 var regex = new Regex(@"^(http)(s)?(://)(www\.)?([^\ ]*)$");
 var isValidUrl = verbalExpression.Test("http://ngskmc-eis.net");

现在,看看相应的VerbalExpression代码来替换它:

 var verbalExpression = new VerbalExpressions()
    	                            .StartOfLine()
    	                            .Then("http")
    	                            .Maybe("s")
    	                            .Then("://")
    	                            .Maybe("www.")
    	                            .AnythingBut(" ")
    	                            .EndOfLine();

MiniProfiler

MiniProfiler 是一个简单但功能非常强大的小型ASP分析器.NET. 它配置所有数据库命令,而不管您是否使用原始ADO.. NET或ORM,如Linq-to-Sql或实体框架. It includes neat functionality, 方法的调用来对部分代码进行显式分析 Step method. 它也支持NoSql数据库,如RavenDb和MongoDb,此外它还提供ASP服务.NET MVC as well as WCF.

Contributors

Giorgi Dalakishvili

Freelance C# Developer

Georgia

Giorgi是一名有十多年经验的软件开发人员. 他从事过各种各样的应用程序,包括移动应用程序, console applications/windows services, large web applications, REST Apis, web services, and desktop/Mac apps. 他还在GitHub上维护着几个开源项目. 他主要使用c#, Xamarin, SQL Server, Oracle, ASP.NET, ASP.. NET Core MVC,实体框架,Android, iOS和WinForms.

Show More

Submit a tip

提交的问题和答案将被审查和编辑, 并可能会或可能不会选择张贴, at the sole discretion of Toptal, LLC.

* All fields are required

Toptal Connects the Top 3% of Freelance Talent All Over The World.

Join the Toptal community.