Спиши, но не точь в точь
Спиши, но не точь в точь

Disclamer: Автор не претендует на глубокие познания в Java или C#. Но очень хотелось разобраться в истории происхождения данного мема. Если заметите неточности, то пишите в комментариях, буду рад исправить.

Небольшая историческая справка

1996 год. Джеймс Гослинг со своей командой выпускают язык, над которым усиленно работали последние 5 лет. Этим языком был Java, который стал большим успехом для компании и получил широкое распространение. И в течении четырех лет всё было безмятежно, язык совершенствовался, комьюнити увеличивалось, пр��блемы решались.

Но вот наступает лето 2000 года. Презентация Microsoft. Демонстрируется продукт над которым они работали последние годы. Этим продуктом был .NET Framework, в рамках демонстрации которого показывают C#.

И смотря на его синтаксис у многих возникли невольные ассоциации с Java.

«Вы, ребятки (из Microsoft), все еще не понимаете, это своего рода Java с удаленными надежностью, производительностью и безопасностью»

Джеймс Гослинг - создатель Java

Создатель C# не оставил это без внимания и отметил, что

C# «не является клоном Java» и «гораздо ближе к C++» по своему дизайну

Андрес Хейлсберг - создатель Turbo Pascal, Delphi, C# и TypeScript

Но несмотря на возражения, шлейф клона Java за C# остался до сих пор. Давайте же попробуем понять какие моменты в C# были явно «вдохновлены» Java

C# вдохновляется Java

ООП как основная парадигма. Пожалуй это первое что бросилось всем в глаза. Оба языка имеют C-подобный синтаксис и в первых версиях обязывали создавать программы в рамках классов. Просто сравните два простейших класса и станет понятно, откуда пошли мемы

// Класс на Java

class Person {
    private int age;
    private String name;

    public Person(int age, String name) {
        this.name = name;
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello, my name is " + name +
            "and I`m " + age + "years old.");
    }
}
// Класс на C#

using System;

class Person {
    private int age;
    private string name;

    public Person(int age, String name) {
        this.name = name;
        this.age = age;
    }

    public void sayHello() {
        Console.WriteLine("Hello, my name is " + name +
            "and I`m " + age + "years old.");
    }
}

Сборщик мусора. На тот момент передовая концепция, которая была скорее в диковинку. Хотя реализация в языках и отличается (Java - алгоритм пометок, C# - алгоритм поколений), не будем отрицать что именно Java значительно популяризировала этот подход

Алгоритм сборки мусора в Java
Алгоритм сборки мусора в Java
Алгоритм сборки мусора в C#
Алгоритм сборки мусора в C#

Механизм рефлексии. Рефлексия — это механизм исследования данных о программе во время её выполнения. Этот механизм в присутствовал еще в языках ассемблера, но Java привнесла его в высокоуровневые языки, переработав подход к ним. Что взял на вооружение в том числе и C#

// Рефлексии в Java

import java.lang.reflect.Method;

public class GetMethodsExample {
    
    public static void main(String...args) {
        Class<GetMethodsExample> c = GetMethodsExample.class;
        Method[] methods = c.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }
    
    public int calcInt(int i) {
        return 0;
    }
    
    public void doSomething() {}
    
    public static void aStaticMethod(String s) {}
    
    private void aPrivateMethod() {}
}
// Рефлексии в C#

using System.Reflection;

public class GetMethodsExample {

    public static void Main() {
        MethodInfo[] methodInfos = Type.GetType("GetMethodsExample").GetMethods();
        foreach(MethodInfo methodInfo in methodInfos) {
            Console.WriteLine(methodInfo.Name);
        }

    }

    public int calcInt(int i) {
        return 0;
    }

    public void doSomething() {}

    public static void aStaticMethod(String s) {}

    private void aPrivateMethod() {}
}

Java вдохновляется C#

Но не все так однозначно и впоследствии некоторые решения из C# перетекли в Java.

LINQ. Language Integrated Query — проект Microsoft по добавлению синтаксиса языка запросов, напоминающего SQL, в языки программирования платформы .NET Framework. Впервые LINQ появился в C# в 2007 году и лишь спустя 7 лет подобный функционал появился в Java в виде Streams API 

// LINQ

class Program {

    static void Main() {
        var numbers = new List<int> {1, 2, 3, 4, 5 };
        var evenNumbers = numbers.Where(n => n % 2 == 0);
        var squares = numbers.Select(n => n * n);
        var sum = numbers.Aggregate((a, b) => a + b);
    }
}
// Streams API

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

public class Example {

    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        Stream<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0);
        Stream<Integer> squares = numbers.stream().map(n -> n*n);
        Optional<Integer> sum = numbers.stream().reduce((a, b) -> a + b);
    }
}

Атрибуты позволяют помечать функции, свойства, классы, методы и т. д. Они появились в C# в 2002 году.  В Java такая возможность была названа аннотациями. Несколько встроенных аннотаций появилось в Java в 2004 году, возможность создания собственных аннотаций с различными полями появилась аж в 2013

// Атрибуты в C#

class Program {

    [Obsolete("Method1 is deprecated, please use Method2 instead.")]
    public void Method() {
        Console.WriteLine("Устаревший метод");
    }

    public void Method2() {
        Console.WriteLine("Актуальный метод");
    }

    public static void Main() {
        new Program().Method();
    }
}
// Атрибуты в Java

public class Program {
    /**
     * @deprecated
     * Method1 is deprecated, please use Method2 instead
     */
    @Deprecated
    public void Method1() {
        System.out.println("Устаревший метод");
    }
    public void Method2() {
        System.out.println("Актуальный метод");
    }

    public static void main(String[] args) {
        new Program().Method1();
    }
}

Делегаты. Делегат - класс, который позволяет хранить в себе ссылку на метод с определённой сигнатурой (порядком и типами принимаемых и типом возвращаемого значений) произвольного класса. Они были в C# с момента релиза. В 2014 году в Java были добавлены делегаты в виде функциональных интерфейсов

// Делегаты

using System;

delegate int Adder(int a, int b);

class Program {

    static void Main(string[] args) {
        Adder adder = (a, b) => a + b;
        int result = adder(5, 10);
        Console.WriteLine(result);
    }
}
// Функциональные интерфейсы

@FunctionalInterface
interface Adder {
    int add(int a, int b);
}

public class Main {

    public static void main(String[] args) {
        Adder adder = (a, b) -> a + b;

        int result = adder.add(5, 10);
        System.out.println(result);
    }
}

Так каков итог?

Смотря на путь языков Java и C# я прихожу к выводу, что в данный момент мем про копирование C# Java потерял свою актуальность. Конечно подобное можно сказать про многие из программистских мемов, но это уже другая история.

Всем позитива!