typescript箭头函数-C# 是 TypeScript 的最佳替代品?

作者 | 内特·希尔

译者| 新月

出品| CSDN(ID:CSDNnews)

TypeScript 非常出色。 它是强类型和快速开发的完美结合,因此它非常易于使用,在许多情况下它是我选择的默认库。 然而,没有完美的语言,在某些情况下 TypeScript 并不是最合适的工具:

性能至关重要(例如即时消息、视频游戏)

需要与 C/C++ 或 Rust 等本机代码交互

需要更严格的类型系统(例如金融系统)

对于这种情况,TypeScript 开发人员最好选择其他语言。 C#、Go、Java 都是非常好的选择。 它们比 TypeScript 快得多,而且每种语言都有自己的优势。 C# 与 TypeScript 配合得很好,让我解释一下原因。

来源:CSDN东方IC1付费下载。 TypeScript 是添加了 C# 的 JavaScript

C# 与 TypeScript 配合得很好,因为它们看起来是同一种语言。 两者都是由 Anders Hejlsberg 设计的typescript箭头函数,在很多方面 TypeScript 都是 JavaScript 添加了 C#。 它们的功能和句型相似,因此很容易将它们组合到同一个项目中。 更重要的是,C# 的语言与 TypeScript 非常相似,因此开发人员非常容易阅读和编写代码。 相比之下,Go 是一种完全不同的语言:没有类,没有继承typescript箭头函数,没有异常,没有包级封装(只有类级封装),语法也完全不同。 当然,这不一定是坏事,但开发人员确实需要重新思考和设计不同的代码,因此同时使用 Go 和 TypeScript 比较困难。 然而,Java 与 C# 非常相似,但仍然缺乏 C# 和 TypeScript 都具有的许多功能。

2. C# 和 TypeScript 的相似之处

也许你已经知道 C# 和 TypeScript 有很多相似之处,比如基于 C 的句子、类、接口、泛型等。下面,让我详细列出两者之间的相似之处:

2.1 异步/等待

首先,C# 和 JavaScript 都使用 async/await 来处理异步代码。 在 JavaScript 中,异步操作由 Promises 表示,应用程序可以等待异步操作的完成。 C#中的Promise虽然是一个Task,但是概念和Promise是一模一样的,也有对应的方法。 以下示例演示了两种语言中 async/await 的用法:

TypeScript 中 async/await 的示例:

async function fetchAndWriteToFile(url: string, filePath:string): Promise<string{
  // fetch() returns aPromise
  const response = awaitfetch(url);
  const text = awaitresponse.text();
  // By the way, we'reusing Deno (https://deno.land)
  awaitDeno.writeTextFile(filePath, text);
  return text;
}

C# 中 async/await 的示例:

using System.IO;
using System.Net.Http;
using System.Threading.Tasks;

async Task<stringFetchAndWriteToFile(string url, stringfilePath) {
  // HttpClient.GetAsync()returns a Task
  var response = await newHttpClient().GetAsync(url);
  var text = awaitresponse.Content.ReadAsStringAsync();
  awaitFile.WriteAllTextAsync(filePath, text);
  return text;
}

下面是 JavaScript 的 Promise API 和等效的 C# Task API:

JavaScript API 相当于 C# API

承诺。 全部()

任务。 等待全部()

承诺。 解决()

任务。 从结果()

承诺。 拒绝()

任务。 来自异常()

承诺。 原型。 然后()

任务。 继续()

新的承诺()

新的任务完成源()

2.2 Lambda表达式和函数链表方法

C# 和 JavaScript 都使用熟悉的 => 语法(即箭头函数)来表示 lambda 表达式。 下面是 TypeScript 和 C# 的比较:

在 TypeScript 中使用 lambda 表达式:

const months = ['January''February''March''April'];
const shortMonthNames = months.filter(month => month.length< 6);
const monthAbbreviations = months.map(month =>month.substr(03));
const monthStartingWithF = months.find(month => {
  returnmonth.startsWith('F');
});

在 C# 中使用 lambda 表达式:


using System.Collections.Generic;
using System.Linq;

var months = new List<string> {"January","February""March""April"};
var shortMonthNames = months.Where(month => month.Length <6);
var monthAbbreviations = months.Select(month =>month.Substring(03));
var monthStartingWithF = months.Find(month => {
  returnmonth.StartsWith("F");
});

上面的例子演示了C#的System.Linq命名空间中的一些技巧,它相当于JavaScript的函数式链表方法。 以下是 JavaScript 中的链表方法和等效的 C# Linq 方法:

JavaScript API 相当于 C# API

Array.prototype.filter()

可数。 在哪里()

Array.prototype.map()

可数。 选择()

Array.prototype.reduce()

可数。 总计的()

Array.prototype.every()

可数。 全部()

Array.prototype.find()

列表。 寻找()

Array.prototype.findIndex()

列表。 查找索引()

2.3 处理空运算符

C# 和 TypeScript 也具有相同的处理 null 的功能:

功能名称语法文档链接

可选属性

财产?

TS:#可选属性,

C#:

非空断言

对象!.属性

TS:#非空断言运算符,

C#:

可选链接

对象?.属性

JS:,

C#:#null-条件运算符 --and-

空合并

目的?? 另类价值

JS:,

C#:

2.4 解构

虽然C#默认不支持链表或类重构,但它支持Tuple和Record重构,用户还可以为自定义类型定义重构。 以下是 TypeScript 和 C# 中的重构示例:

TypeScript 中重构的反例:

const author = { firstName: 'Kurt', lastName: 'Vonnegut' };
// Destructuring an object:
const { firstName, lastName } = author;

const cityAndCountry = ['Indianapolis''United States'];
// Destructuring an array:
const [city, country] = cityAndCountry;

C# 重构的反例:


using System;

var author = new Author("Kurt""Vonnegut");
// Deconstructing a record:
var (firstName, lastName) = author;

var cityAndCountry = Tuple.Create("Indianapolis","United States");
// Deconstructing a tuple:
var (city, country) = cityAndCountry;

// Define the Author record used above
record Author(string FirstName, string LastName);

2.5 命令行界面(CLI)

我的开发方法是使用文本编辑器编写代码,然后在终端中运行命令,构建并运行。 对于 TypeScript,这意味着使用 Node 或 deno 命令行界面 (CLI)。 C# 也有一个类似的 CLI,称为 dotnet(以 C# 的 .NET 运行时命名)。 以下是使用 dotnet CLI 的一些反例:

mkdir app && cd app
# Create a new console application
# List of available app templates:https://docs.microsoft.com/dotnet/core/tools/dotnet-new
dotnet new console
# Run the app
dotnet run
# Run tests (don't feel bad if you haven't written those)
dotnet test
# Build the app as a self-contained
# single file application for Linux.
dotnet publish -c Release -r linux-x64

2.6 基本功能(类、泛型、错误和枚举)

这些是 TypeScript 和 C# 之间更基本的相似之处。 下面的反例是对这几个方面的介绍:

TypeScript 类的示例:

import { v4 as uuidv4 } from'https://deno.land/std/uuid/mod.ts';

enum AccountType {
  Trial,
  Basic,
  Pro
}

interface Account {
  id: string;
  type: AccountType;
  name: string;
}

interface Database {
  insert(item: T):Promise;
  get(id: string):Promise;
}

class AccountManager {

  constructor(database:Database) {
    this._database =database;
  }

  asynccreateAccount(type: AccountType, name: string) {
    try {
      const account = {
        id: uuidv4(),
        type,
        name;
      };
      awaitthis._database.insert(account);
    } catch (error) {
        console.error(`Anunexpected error occurred while creating an account. Name: ${name}, Error:${error}`);
    }
  }

  private _database:Database;
}

C# 类的示例:

using System;
using System.Threading.Tasks;

enum AccountType {
  Trial,
  Basic,
  Pro
}

record Account(string Id, AccountType Type, string Name);

interface IDatabase<T> {
  Task Insert(T item);
  Task Get(stringid);
}

class AccountManager {

  publicAccountManager(IDatabase database) {
    _database = database;
  }

  public async voidCreateAccount(AccountType type, string name) {
    try {
      var account = newAccount(
       Guid.NewGuid().ToString(),
        type,
        name
      );
      await_database.Insert(account)
    } catch (Exceptionexception) {
     Console.WriteLine($"An unexpected error occurred while creating anaccount. Name: {name}, Exception: {exception}");
    }
  }

  IDatabase_database;
}

3.C#的其他优点

与 TypeScript 的相似性并不是 C# 的唯一优点,它还有其他优点:

3.1 与原生代码结合

C# 的最大优势之一是它可以深入本机代码。 正如本文开头提到的,TypeScript 并不擅长与 C/C++ 代码结合。 Node.js 有一个支持原生 C/C++ 的插件,称为 Node-API,但它需要为原生函数编译额外的 C++ 包装器,将原生类型转换为 JavaScript 对象,反之亦然,类似于 JNI 的工作方式。 C#可以直接调用原生函数,只需要把库放在应用程序的bin目录下,然后在C#中将API定义为外部函数即可。 然后,您可以像 C# 函数一样使用外部函数,.NET 运行时将处理 C# 数据类型和本机数据类型之间的转换。 例如,如果本机库导入以下 C 函数:

int countOccurrencesOfCharacter(char *stringchar character) {
    int count = 0;
    for (int i = 0;string[i] != ''; i++) {
        if (string[i] ==character) {
            count++;
        }
    }
    return count;
}

然后可以像这样从 C# 调用它:

using System;
using System.Runtime.InteropServices;

var count = MyLib.countOccurrencesOfCharacter("C# is prettyneat, eh?"'e');
// Prints "3"
Console.WriteLine(count);

class MyLib {
    // Just placeMyLibraryName.so in the app's bin folder
   [DllImport("MyLibraryName")]
    public static externint countOccurrencesOfCharacter(string str, char character);
}

该方法可以通过C链接访问任何动态库(.so、.dll或.dylib),也就是说,你可以轻松调用C、C++、Rust、Go或其他语言编写的代码,只要经过编译到机器代码就是这样。 本机交互的其他应用包括:

3.2 事件

C# 的一个独特功能是它提供一流的风暴支持。 在 TypeScript 中,可以实现 addEventListener() 方法让客户端监听风暴,而 C# 有 event 关键字,可以用来定义风暴,通过简单的句子(不需要需要 TypeScript 自动遍历所有风暴监听器并在 try/catch 块中执行它们)。 例如,我们可以让 Connection 类定义一个 MessageReceived 事件,如下所示:

class Connection {
    // AnAction is a callback that accepts a string parameter.
    public eventAction<string> MessageReceived;
}

使用Connection代码,可以通过+=操作符为MessageReceived添加处理函数,如下:

var connection = new Connection();
connection.MessageReceived += (message) => {
   Console.WriteLine("Message was received: " + message);
};

Connection类可以在内部调用MessageReceived来为所有监听者触发MessageReceived风暴:

// Raise the MessageReceived event
MessageReceived?.Invoke(message);

4、其他优点

性能:C# 速度很快。 C# 的 ASP.NET (Core) Web 框架仍然在 Techempower 的基准测试中名列前茅,而 C# 的 .NET CoreCLR 运行时在每个主要版本中都获得了性能增强。 C# 具有良好性能的原因之一是,通过使用结构而不是类,应用程序可以最大限度地减少甚至完全消除垃圾收集。 因此,C# 在视频游戏编程中非常流行。

游戏和混合现实:C# 是最流行的游戏开发语言之一,被 Unity、Godot 甚至 Unreal 等游戏引擎使用。 C# 在混合现实中也很流行,因为 VR 和 AR 应用程序是用 Unity 编写的。

由于 C# 拥有第一方库、工具和文档,因此某些任务非常容易实现,例如,用 C# 创建 gRPC 客户端比 TypeScript 容易得多。 相反,在 Node.js 中使用 TypeScript 时,有必要找出正确的模块和工具组合,以正确生成 JavaScript gRPC 客户端以及相应的 TypeScript 类型。

高级特性:C#有很多其他语言没有的特性,比如运算符重载、析构函数等。

5. 总结

正如前面提到的,没有完美的语言。 设计语言时总是需要权衡,因此有些语言速度更快但使用起来不太困难(例如Rust的借用检测)。 另一方面,有些语言非常好用,但优化一般性能的难度会降低(比如JavaScript的动态语言特性)。 正因为如此,我相信拥有一组相似的语言特别有用:每种语言都有自己的优点,但都很相似并且可以很好地协同工作。 例如,这是我选择的一组语言:

5.1 TypeScript5.2 C#C++

参考链接:

推荐阅读:
20 个 .NET 6 新增的 API
.NET 不受 美国出口管理条例(EAR) 的约束
C# 中的浅表拷贝和深层拷贝
C#多线程编程-必知必会
MASA MAUI Plugin 安卓蓝牙低功耗(一)蓝牙扫描
深度学习库 SynapseML for .NET 发布0.1 版本

点击下方卡片关注DotNet NB

一起交流学习

▲ 点击上方卡片关注DotNet NB,一起交流学习

请在公众号后台

回复 【路线图】获取.NET 2021开发者路线图
回复 【原创内容】获取公众号原创内容
回复 【峰会视频】获取.NET Conf开发者大会视频
回复 【个人简介】获取作者个人简介
回复 【年终总结】获取作者年终总结
回复 加群加入DotNet NB 交流学习群

长按识别下方二维码,或点击阅读原文。和我一起,交流学习,分享心得。