阅读更多

2顶
2踩

编程语言
如果我们可以同时拥有 C# 和 Java 世界的最好特性,那会是什么样呢?

完美的编程语言并不存在,我希望我们可以在这一点上达成一致。开发新语言往往是为了克服另一种语言的弊端,又不可避免的在某些方面上健壮一些,却在另一些方面上存在不足。

C# 与 Java 都起源于 C/C++ 语言,他们在面向对象方面有许多相似之处。除了 Java JVM 和 C# .NET CLR 有许多相同结构上的相似性之外,他们各自的开发团队都有各自的发展方向,他们关注的是各自的语言应该成为什么样子。

我们并不想纠结于某一个语言比另一个语言好,我们只想罗列出 C# 开发者能用到而 Java 中没有的那些特性而已。

下面我们开始吧。

1. LINQ

LINQ (Language-Integrated Query,语言集成查询) 于 2007 年引入到 C#,以帮助开发人员从各种数据源查询数据。使用它,我们可以在无需考虑正在调用的特定数据库的语法来编写查询语句。LINQ provider 所提供的一个组件将查询转换为下层数据源可读的格式。例如,如果我们需要从 SQL 数据库查询数据,LINQ to SQL provider 程序将把 LINQ 查询转换成 T-SQL,以便数据库可以理解它。

要在 LINQ 中执行查询操作,首先获取数据库,然后创建查询,最后执行查询。在 LINQ to Object 查询中,这可能仅像一样代码一样简单,而不是为每个循环编写嵌套的复杂迭代。

例如,我们来看看这个代码,用于在 C# 中从列表中过滤 2 位数。

首先,在不使用 LINQ 的情况下:
List<int> FilterTwoDigitNumbersWithoutLinq(List<int> numbers)
{
    var tens = new List<int>();
    
    for (var i=0; i < numbers.Count(); i++)
    {
        if ((9 < numbers[i]) && (numbers[i] < 100))
        {
            tens.Add(numbers[i]);
        }
    }
    
    return tens;
}

如果使用 LINQ 查询语法形式:
List<int> FilterTwoDigitNumbersWithLinq(List<int> numbers)
{
    return (from a in numbers
            where (a > 9 && a < 100)
            select a).ToList();
}

或者是方法语法形式:
List<int> FilterNonTwoDigitNumbersWithLinq2(List<int> numbers)
{
    return numbers.Where(a => a > 9 && a < 100).ToList();
}

这里两种语法都是正确的,唯一的区别就是查询语法看起来更像是 SQL 语句而方法语法使用 lambda 表达式(当然,看起来很像我们在 Java 里写的某些代码)

综述:LINQ 所依赖的许多特性,如 lambda 表达式(就 LINQ 来说非常有用),已经在 Java 中有了等效的实现,尽管我们可以使用流和 lambda 来查询数据,但 LINQ 简化了整个过程并且移除了很多在 Java 中存在的冗余代码。

2. Struct

C# 中的结构体类似于类。实际上,一个 struct 甚至可以被认为是一个“轻量级类”,因为它可以包含构造函数、常量、方法等等。一个结构体和一个类之间最大的区别在于结构是值类型,而类是引用类型。

相比于创建类,编写结构体最重要的好处是在构造一个值类型时比在构造引用类型时更容易确保值语义。如 Microsoft 的文档所述,“struct 类型的变量直接包含结构体的数据,而类类型的变量包含对数据的引用。”因此,对比使用类时,使用结构体的好处之一是,从代码的其他部分更改其值的唯一方法是将其作为参考进行显式传递。

微软的开发人员建议对于那些小于 16 字节、生命周期短、不改变的而且不常装箱的类型,使用结构体(struct)而不是类(class)。在这种情况下,使用结构体可能会比使用类更有效率,因为它会保存在栈而不是堆中。

比如:
public struct Point
    {
        public int X;
        public int Y;

        public Point(int X, int Y)
        {
            this.X = X;
            this.Y = Y;
        }

        public static Point operator +(Point p1, Point p2)
        {
            return new Point(p1.X + p2.X, p1.Y + p2.Y);
        }

        public override string ToString()
        {
            return ($"({X}, {Y})");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Point point1 = new Point(1, 5);
            Point point2 = new Point(2, 3);

            Console.WriteLine("The addition of both points will result in: {0}", (point1 + point2));

            Console.ReadKey();
        }
}

小结:很多情况下使用结构体可以节省内存分配和释放的时间,这确实很有吸引力。然而事实是值类型拥有自己的存储空间。无论结构体拥有如何明显的优点和缺点,这在 Java 中都不需要操心。

3. Async/Await

在一段代码中调用 async,或者更明确地调用方法,这个方法都会在另一个线程上执行,不会阻塞当前线程。当代码运行到 await 命令的时候,它会继续运行(await 的语句)。如果这时 async 代码还没有完成,那么执行中的程序会返回到调用点。

这有助于提高应用程序总体的响应速度,以及减少性能瓶颈。在应用程序访问 Web 和进行所有 UI 相关的活动时,使用异步程序非常重要。相对于以前的异步编程实现,使用 async/await 可以保留你代码的逻辑结构,而编译器则会担负起以前由开发者担负的重担。

示例:
class Program
    {
        public static void Main()
        {
            Console.WriteLine("Hey David, How much is 98745 divided by 7?");

            Task<int> david = ThinkAboutIt();

            Console.WriteLine("While he thinks, lets chat about the weather for a bit.");
            Console.WriteLine("Do you think it's going to rain tomorrow?");
            Console.WriteLine("No, I think it should be sunny.");

            david.Wait();
            var davidsAnswer = david.Result;

            Console.WriteLine($"David: {davidsAnswer}");

            Console.ReadKey();
        }

        private static async Task<int> ThinkAboutIt()
        {
            await ReadTheManual();

            Console.WriteLine("Think I got it.");

            return (98745 / 7);
        }

        private static async Task ReadTheManual()
        {
            string file = @"D:\HowToCalc.txt";

            Console.WriteLine("Reading a manual.");
            
            using (StreamReader reader = new StreamReader(file))
            {
                string text = await reader.ReadToEndAsync();
            }

            Console.WriteLine("Done.");
        }
}

输出:
// Possible Output:

Hey David, How much is 98745 divided by 7?
Reading a manual.
While he thinks, lets chat about the weather for a bit.
Do you think it's going to rain tomorrow?
No, I think it should be sunny.
Done.
Think I got it.
David: 14106

概要:CompletableFutures 无疑可以使我们更趋近于拥有等效于 C# 和 Java 所拥有的异步编程中的能力。尽管如此,使用它所带来的复杂性使其易用度不能与使用 async /await 关键字进行的实现相提并论。

4. Lazy<T> 类

无论使用 C# 还是 Java,很多人都已经实现了延迟初始化 (或实例化),因此对象要在第一次使用的时候才会被创建。有一种常见的例子是将延迟初始化用于应用程序启动的时候加载大量对象,但实际需要初始化的对象可能只有少数几个。这种情况下,我们希望辨别哪些是不需要在这里初始化的。只初始化那些确实需要初始化的对象可以提升应用程序的性能。

小结:最近,Lambda 表达式引入到 Java 8 之后,在 Java 中实现延迟加载(还有不少其它事情)变得更容易了。不过,在 C# 中我们可以使用语义化的 Lazy<T> 封装类来延迟初始化任何类库或用户指定的类型。

5. 一些等价的关键词

语言中的有用功能不一定像在 C# 中的 LINQ 或 Java 中的模块一样大。这里有一些可以帮助 C# 开发人员的关键字,它们在 Java 中并没有:

a. as

C# 中的 as 关键字会尝试安全地将对象转换为某个类型,如果不能转换的话,就返回 null。与 Java 的instanceof 几乎等同,但它是一个布尔值,如果类型匹配则返回 true,否则返回 false。

b. Yield

在 C# 中使用  Yield 和 return yield 来进行自定义且状态化的迭代,不需要显式创建额外的类,也不需要创建临时集合。在 Java 中我们实现迭代最好的选择是使用外部库或使用 Java 8 引入的 Lambda 表达式。

c. var

Var 是一种隐式类型,其实际类型由编译器决定,其功能相当于写一个显式类型 (比如 int, string 等)。它除了可以减少一些按键之外,var 还允许用于匿名类型,而匿名类型在 LINQ 中很常用。我们期待看到“var”标识,备受瞩目的 Java SE 9 将实现“将类型推导扩展到定义并初始化局部变量时。”

d. Checked

C# 中,我们使用 checked 关键字显式启用对整型表达式的溢出检查。如果表达式的运算结果超出目标类型的范围,我们可以使用 checked 强制要求运行时抛出 OverflowException。这十分有用,因为常量表达式会在编译期进行溢出检查,而非常量表达式不会。

工具生态系统

Java 和 C# 之间存在大量的不同之外,当然,其中一些源于 Java 和 .NET 框架的不同。这些不同之处也导致了一些工具在兼容性方面的差异,比如 OverOps 在生产监控和错误跟踪方面的差异。

OverOps 向开发者展示生产中每个错误整个调用栈的全部源代码和变量状态。目前在 .NET 框架上并没有与之相同的内容,不过在接下来的几个月内会有一些变化。想了解更多信息,请点击这里加入我们 .NET Beta 的等候名单,如果你是 Java 开发者可以去 www.overops.com 查看演示。

最后的思考

在快结束时候,我们这里提到的大部分功能都在代码长度和简洁程度方面对 C# 开发者有所帮助,这些代码不能在 Java 中编写。事实上这些特性也或多或少说明了 Java 语言冗长的问题,包括最近版本更新带来的 Lambda 表达式。诚然,很多这些存在于 C# 而不存在于Java 中的特性在常规使用中提供了比使用 Lambda 更简洁的语法。

再次说明,我们不想卷入没完没了的关于哪种言更好的争论,我们只是在这里指出两种语言之间的一些区别。我们是否遗漏了某些你希望 Java 拥有的特性?请在评论中告诉我们!
来自: oschina
2
2
评论 共 6 条 请登录后发表评论
6 楼 wangyuvirgo 2017-08-23 16:27
按你这么说,谷歌、甲骨文应该马上听你,转为用C#开发产品,android也够傻逼的,用什么java开发,应该用你说的什么C#
5 楼 wangjia 2017-08-23 09:27
这是宣战贴么,该用JAVA的地方还是用JAVA
4 楼 soualliron 2017-08-22 23:46
c#好多语法糖,但糖嘛,虽然甜,不一定会有什么营养
3 楼 lizhuang 2017-08-22 11:58
PHP才是最好的程序语言。
2 楼 kettas 2017-08-22 08:02
这样比有毛用。各有各的优势。C#替代不了Java,Java替代不了C#!
1 楼 君淋天下 2017-08-21 16:14
单独语言特性比较,C#比java强大很多

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • c vs java_C# vs Java:C# 五个不可替代的特性瞬间秒杀 Java

    原标题:C# vs Java:C# 五个不可替代的特性瞬间秒杀 Java如果我们可以同时拥有 C# 和 Java 世界的最好特性,那会是什么样呢?完美的编程语言并不存在,我希望我们可以在这一点上达成一致。开发新语言往往是为了克服...

  • java和c#混合语言编程,C#秒杀Java的五个不可替代的特性,完美的编程语言并不存在...

    原标题:C#秒杀Java的五个不可替代的特性,完美的编程语言并不存在如果我们可以同时拥有 C# 和 Java 世界的最好特性,那会是什么样呢?完美的编程语言并不存在,我希望我们可以在这一点上达成一致。开发新语言往往是...

  • 挑战 Java 霸主之位?C# 五个不可替代的特性瞬间秒杀 Java

    一门新语言的诞生往往是为了克服另一种语言的弊端,但在保证新语言健壮性的同时却似乎又不可避免在另一方面出现不足。 纵观大小 600 多种编程语言,我们究竟该如何选择适合自己的开发语言?是根据兴趣、工作需求、...

  • d c java 性能比较_对决 | C#中5个不可替代的特性秒杀Java

    原标题:对决 | C#中5个不可替代的特性秒杀Java歌名:Destiny -太陽の花-歌手:島谷ひとみ如果我们可以综合来自 C#和 Java最好的特性,可以得到什么样的东西?没有完美的编程语言。如果没有其它问题,我希望我们能...

  • 10万字208道Java经典面试题总结(附答案)

    JDK中包含JRE,JDK中有一个名为jre的目录,里面包含两个文件夹bin和lib,bin就是JVM,lib就是JVM工作所需要的类库。 2、== 和 equals 的区别是什么? 对于基本类型,==比较的是值; 对于引用类型,==比较的是地址...

  • Java面试题,208道

    前言 最近有很多粉丝问我,有什么方法能够快速提升自己,通过阿里、腾讯、字节跳动、京东等互联网大厂的面试,我觉得短时间提升自己最快的手段就是背面试题,...5、String 属于基础的数据类型吗? 6、String str=.

  • java面试大全

    Java面试大全

  • 【DotNetGuide】C#/.NET/.NET Core学习、工作、面试指南

    现如今网上关于Java、前端、Android、Golang...等相关技术的学习资料、工作心得、面试指南一搜都是一大把,但是咱们C#/.NET的相关...并不是没有人写,而是因为网上的资料和文章太零散了,缺少一个这方面汇总的知识库。

  • java日常学习

    项目实战: 秒杀:spring-boot-seckill: 从0到1构建分布式秒杀系统,脱离案例讲架构都是耍流氓,交流群:933593697 RuoYi: 基于SpringBoot的权限管理系统 易读易懂、界面简洁美观。 核心技术采用Spring、MyBatis、...

  • Java开发常见专业术语

    脚本(Script),是使用一种特定的描述性语言,依据一定的格式编写的可执行文件。 例如:sql脚本 2. HTTP协议 HTTP协议,即超文本传输协议(Hyper text transfer protocol)。是一种详细规定了浏览器和万维网...

  • Java210道常见的面试

    JDK中包含JRE,JDK中有一个名为jre的目录,里面包含两个文件夹bin和lib,bin就是JVM,lib就是JVM工作所需要的类库。 2、== 和 equals 的区别是什么? 对于基本类型,==比较的是值;对于引用类型,==比较的是地址;...

  • Java面试题整理(带答案)

    Java面试题整理

  • 【java EE】Redis基础及应用

    CAS法是用一个每次都会查询和更新的字段替代版本号,这里用stock 一人一单 优惠券或者秒杀活动的目的是为了吸引新用户,因此不能让一个用户把所有东西都抢走了。所以需要额外判断用户 当前下单数是否&gt;0。 这一步...

  • 2022年Java 工程师面试题

    35 内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、 Redis、MySQL、Spring、Spring Boot、Spring Cloud、RabbitMQ、Kafka、 Linux 等技术栈Java 工程师面试题 2020 字节Java 工程师面试题....

  • java笔记 自己用

    java基础知识总结,参考: https://www.cnblogs.com/schiller-hu/p/10662429.html 或 https://www.cnblogs.com/jacking0325/p/10859350.html (通俗易懂) 继承: 好处: 1.减少代码的冗余性 2.提高代码的复用性 3...

  • JAVA基于JSP的在线人才招聘求职系统【数据库设计、论文、源码、开题报告】

    【代码】JAVA基于JSP的在线人才招聘求职系统【数据库设计、论文、源码、开题报告】

  • 【大学四年自学Java的学习路线】写了一个月,这是一份最适合普通大众、非科班的路线,祝你零基础快速找到一份满意的工作

    1)“零基础”意味着我提供的学习路线不能太难,或者说应该是循序渐进的。 2)“自学”意味着我提供的学习素材不能太枯燥,或者说应该是幽默风趣的。 3)“找到工作”意味着学习周期要尽可能的短,但还要学有所成...

  • Java基础知识学习:Java入门和背景知识

    计算机语言的发展 计算机已经成为人大脑的延伸 ...  可以这么说, 计算机已经成为了人类身体的延伸、大脑的延伸,成为不可或缺的一部分。未来,计算机将真的进入人体、进入大脑,真正成为人体的一部分。比如,在

  • PHP语言基础知识详解及常见功能应用.docx

    本文详细介绍了PHP的基本语法、变量类型、运算符号以及文件上传和发邮件功能的实现方法,适合初学者了解和掌握PHP的基础知识。

  • 公司金融课程期末考试题目

    公司金融整理的word文档

Global site tag (gtag.js) - Google Analytics