« Voltar
em .net c# java

C#: imitação ou inovação? - parte 1.

Esses dias navegando pelas internets eu dei de cara com um artigo muito legal do Michael Shpilt, um desenvolvedor israelense, onde ele escreveu sobre as funcionalidades do C# e se elas foram imitadas de outras linguagens ou se foram uma inovação.

Achei muito interessante e entrei em contato com ele pra ver se ele me autorizava a traduzir os posts, e felizmente ele autorizou :)

Segue então a tradução do post do Michael, que você pode ler na íntegra aqui.


Liderada por Anders Hejlsberg, por volta dos anos 2000 a Microsoft lançou a linguagem C#. A linguagem, assim como o .NET Framework tinham um propósito estratégico. A Microsoft queria criar uma linguagem mais acoplada ao Windows, trazendo clientes ao ecossistema Windows e os produtos da empresa. Talvez tenha sido parte da extratégia "Embrace, extend and extinguish" que a Microsoft teve por um tempo, mas que agora é não existe mais (felizmente).

A linguagem surgiu como uma resposta ao Java, que se tornou bastante popular na época. C# tinha muito em comum com Java e o até chegou a ser chamada de "imitação" por James Gosling, o criador do Java.

Desde sua versão inicial em 2000, C# evoluiu muito, se distanciando do Java e se tornando uma das linguagens mais populares do mundo. Isso veio com uma longa lista de funcionalidades que tornaram o que o C# é hoje em dia.

Algumas dessas funcionalidades foram ideias originais e outras cópias de outras linguagens.

(O Michal deixou claro que não acha - e eu também não - que copiar algo de outras linguagens seja algo ruim. Todas as linguagens de sucesso copiaram uma ou outra funcionalidade já inventada em outra).

C# 1.0

Essa foi a primeira versão e foi lançada em 2002. Ela tinha as seguintes funcionalidades:

Classes – Já existiam há um tempo em C++ e Java. Imitação.

Structs – Se comportam diferente de structs em C++, mas nem tipos por valor nem a ideia de struct por si só eram novas. Imitação.

Interfaces – Já existiam em Java. Imitação.

(Quando o Michael fala que classes já existiam em Java, ele não quer dizer que elas foram inventadas no Java, mas é apenas um exemplo de uma linguagem que já implementou essa funcionalidade antes do C#).

Delegates – Não era um conceito novo.

public delegate int MathOperation(int x, int y);  

C já tinha function pointers, que era basicamente a mesma coisa. O que temos no C# já existia em Algol em 1968. Imitação.

Eventos – juntamente com os delegates foi possível implementar o padrão oberver lindamente usando eventos.

public event EventHandler SomethingHappened; 

SomethingHappened += OnSomethingHappened; 

SomethingHappened.Invoke(this, new EventArgs());  

Eventos também não eram novidade e já existiam no Delphi. Imitação.

Propriedades – uma solução elegante para substituir getters e setters infinitos do Java.

private int _number;  
public int Number  
{
    get { return _number; }
    set { _number = value; }
}

Propriedades já existiam no Delphi, mas com uma sintaxe diferente. Imitação.

Attributes – Uma inovação do C# que posteriormente foi imitada pelo Java com as Annotations.

[Conditional("DEBUG")]
void LogEntry()  
{
    // ...
}

Ainda que não mencionada como uma funcionalidade da linguagem, o fato do C# ser uma linguagem com Garbage Collection é uma imitação do Java.

C# também parece ter sido bastante influenciada pelo Delphi. E isso não é uma coincidência. O antigo trabalho do Anders Hejlsberg era justamente chefe de arquitetura do Delphi.

Apesar de todas as imitações, o C# 1.0 implementou muitas funcionalidades com uma síntaxe mais agradável e combina elas em uma linguagem elegante. Tudo isso colocou C# como uma alternativa viável ao Java.

C# 2.0

Em 2005 o C# 2.0 foi lançado com novas e poderosas funcionalidades:

Generics – Generics foi implementada em Java um ano antes, em 2004.

List<int> list = new List<int>();  
list.Add(5);  

Mesmo antes disso, uma funcionalidade similar chamada Templates já existia em C++. A implementação de Generics do C# é melhor que do Java, mas no fim das contas é uma imitação.

Tipos parciais – Parecido com C++, onde você pode declarar todas funções no cabeçalho, mas implementá-las em diferentes arquivos. Por não ser necessário ter um arquivo de cabeçalho com todas as funções, podemos dizer que isso é uma inovação do C#.

Métodos anônimos – com métodos anônimos, ficou muito mais agradável trabalhar com delegates no C#.

delegate int Del(int x);  
Del add5 = delegate(int k) { return k + 5;};  
int x = add5(11);//16  

Mas não é um conceito novo: funções anônimas existem em programação há um bom tempo (por exemplo, em Haskell). Imitação.

Tipos nullable – tipos nullable meio que existem naturalmente em linguagens dinâmicas, mas foi um conceito novo em lingaugem estaticamente tipadas.

int? number;  

Funciona muito bem com structs. Inovação.

Iterators – Iteratores são encontrados em C++ STL, Scala, Java e até em linguagens mais antigas.

//Example from Microsoft Docs
static void Main()  
{  
    foreach (int number in SomeNumbers())  
    {  
        Console.Write(number.ToString() + " ");  
    }  
    // Saída: 3 5 8  
}  

public static System.Collections.IEnumerable SomeNumbers()  
{  
    yield return 3;  
    yield return 5;  
    yield return 8;  
}

O Java lançou o laço for each com o J2SE 5.0 um ano antes. O que o c# inova é a sintaxe "yield return" pra criar coleções iteráveis. Imitação.

Covariância e contravariação – Nessa versão, covariância e contravariação são suportadas em objetos, arrays e delegates. Em Generics ainda não. Java já suportava covariação em tipos de retorno a esse ponto. Não é certo se Scala implementou isso antes que o C#. De qualquer forma, vou ter que classificar essa como imitação.

Classes estáticas – Uma classe estática que não tem nada a não ser métodos/propriedades/atributos estáticos foi único no C# nesse ponto. Inovação.

Nessa versão 2.0, C# não adicionou nada de muito inovador na linguagem, a não ser funcionalidades que que Java já tinha como Iterators e Generics. De qualquer forma, a implementação e síntaxe do C# já era superior à do competidor direto. Ou seja: C# estava imitando Java, mas fazendo melhor.

C# 3.0

Em 2007 a versão 3.0 foi lançada com muitas novas funcionalidades:
Expressão lambda – a expressão lambda introduz uma sintaxe elegante para definir uma função anônima. Funções anônimas já existiam em programação bem antes de 2007, mas a expressão lambda é relativamente nova. Essa síntaxe se tornou tão popular que eventuamente foi implementada em linguagens como Ruby, Java, Javascript, Swift e C++.

(a, b) => a + b

Mas é inovação?

Aparentemente não. Eu vi que tanto a versão 98 do Haskell e Scala versão 1.3.0 (2004) já implementavam funções lambda com uma síntaxe bem parecida.

Scala:

(x: int, y: int) => x * y

Haskell:

add = \x y -> x+y  

Ou seja, imitação.

Extension methods – a possibilidade de adicionar funcionalidades à qualquer classe da CLR sem mexer diretamente nela:

public static class StringExtensions  
{
    public static char SecondChar(this string str)
    {
         return str[2];
    }
}
...
Console.WriteLine("12345".SecondChar()); //2  

A essa altura, esse "truque" já era amplamente utilizado em linguagens dinâmicas como Ruby e é conhecido como Monkey Patching. Mas foi a priemira vez que foi visto em linguagens fortemente tipadas como C#. Ainda assim, uma imitação.

LINQ com síntaxe baseada em queries – aqui foi introduzido o LINQ. C# passou a permitir que você escrevesse "queries" em coleções e tornou manipular e transformar dados com pouco código.

IEnumerable<int> highScoresQuery =  
     from score in scores
     where score > 80
     orderby score descending
     select score;

A síntaxe baseada em queries por si só é uma imitação de linguagens como SQL. Mas, ao contrário do SQL, LINQ é type-safe e é a primeira de seu tipo em uma linguagem orientada a objeto. Então, apesar da imitação na parte da síntaxe, é uma inovação.

LINQ com síntaxe de método – se aproveitando de Extension Methods e Lambdas, foi possível implementar LINQ no C# de uma forma funcional:

List<int> scores = new List<int>() {55,65,75,48,35,67,92,75};  
var highScoresMethodSyntax =  scores  
            .Where(score => score > 80)
            .OrderByDescending(score => score);

Essa funcionalidade mudou o jogo para o C# e se tornou extremamente popular. Inovação.

Expression trees – essa não é necessariamente uma funcionalidade da linguagem. É uam forma de adicionar metadata à sua query LINQ, que é traduzida para SQL e eventualmente executada no banco de dados.
Tipos anônimos – outra funcionalidade inovadora do C#.

var productQuery =  
    from prod in products
    select new { prod.Color, prod.Price };

foreach (var v in productQuery)  
{
    Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}

Funciona muito bem com LINQ e permite a escrita de código extremamente elegante. Inovação.

Variáveis locais implicitamente tipadas:

var name = "Michael";  

A keyword var foi uma necessidade para dar suporte aos tipos anônimos, já que tipos anônimos não tem nome (nem tipo):

var anonym = new {FirstName = "John", LastName = "Smith"};  
Console.WriteLine(string.Format("Full name: {0} {1}",  
    anonym.FirstName, anonym.LastName));

A keyword var é a primeira de seu tipo em linguagens fortemente tipadas. Apesar de não ter encontrado nada parecido inicialmente, há uma linguagen de programação chamada Modula-3 que tem uma implementação parecida com o var do C#. Modula-3 foi lançada em 1989, portanto uma imitação. Obrigado a Darren Morby por apontar isso.

Eventuamente, a mesma funcionaliadde foi adotada pelo Java, C++ (keywork auto) e Kotlin.

Métodos parciais – Um complemento aos tipos parciais que foram adicionados na versão 2.0. Essa funcionalidade permite declarar um método em uma parte de um tipo e implementá-lo em outro. Muito parecido com os arquivos header que temos no C++. Imitação.

Initializers para objetos e collections – uma síntaxe mais curta e simples para inicializar objetos e coleções. Por exemplo:

List<Gato> gatos = new List<Gato>  
{
    new Gato(){ Nome = "Sylvester", Idade = 8 },
    new Gato(){ Nome = "Whiskers", Idade = 2 },
    new Gato(){ Nome = "Sasha", Idade = 14 }
};

Initializers para coleções não são nenhuma novidade. Por exemplo em Scala:

val fruit = List("apples", "oranges", "pears");  

Não encontrei o equivalente a initializers para objetos, já que outras linguagens não tem propriedades e dependem de construtores para esse tipo de inicialização. De uma forma geral, é uma imitação.

Auto implemented properties – uma síntaxe mais curta para propriedades que não requer criação de atributos explicitamente e lógica nos getters e setters:

public string Name { get; set; }  

Como mencionado antes, propriedades já existiam no Delphi e também no Visual Basic a essa altura. Mas as auto-implemented properties são uma inovação do C#. O Visual Basic imitou essa mais tarde com o .NET 4.0.

Nessa versão, a galera do C# adicionou algumas funcionalidades matadoras que mudaram o jogo na guerra das linguagens. LINQ e Lambda expressions em especial se tornaram extremamente populares.

Em contraste a isso Java, a maior concorrente, não lançou nenhuma nova feature de linguagem. Nesse ponto era o Java que estava correndo atrás, e foi assim por um bom tempo. Por exemplo, Java adicionou funções Lambda só no Java 8, em 2014.

Conclusão

Desde o release inicial em 2002, C# lançou 3 versões e em 2008 já era uma linguagem bem madura.

C# se tornou um player grande na guerra das linguagens, ganhando uma grande fatia do mercado de desenvolvimento.

Em 2008, quando a versão 3.0 foi lançada, Java era a linguagem mais popular no mundo. De acordo com o Tiobe, C# ficava em sétimo lugar na época (depois de Java, C, C++, PHP, Perl e Python)

Fontes

C# History – https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-version-history
Comparison of C# and Java – https://en.wikipedia.org/wiki/ComparisonofCSharpandJava
Java version history – https://en.wikipedia.org/wiki/Java
version_history


Quer ficar em dia com os meus posts e novidades?
Participe do inscreva na minha newsletter, me segue no Twitter e na minha página!

comments powered by Disqus