Março 2010 - Posts

LINQ With C# (Portuguese)

Tal como outros métodos da API do LINQ que extraem valores escalares de sequências, o Single tem um correspondente SingleOrDefault.

A documentação de SingleOrDefault diz que retorna um único e específico elemento de um sequência de valores, ou um valor por omissão se tal elemento não exisitir, although, in my opinion, it should state that it retorna O único e específico elemento de um sequência de UM valor, ou um valor por omissão se tal elemento não exisitir. Não obstante, o que este método faz é retornar o valor por omissão para o tipo da fonte e a sequÊncia for vazia ou, tal como Single, lançar uma excepção se a sequência tiver mais de um elemento.

Recebi alguns comentários à minha última entrada dizendo que poderia ser usado o método SingleOrDefault para evitar a excepção.

Bem, apenas “resolve” metade do “problema”. Se a sequência tiver mais de um elemento, uma excepção será lançada, de qualquer modo.

No final, tudo se resume a semântica e intenção. Se o esperado é que a sequência possa ter um ou nenhum element, então deve ser usado o método SingleOrDefault. Se não é esperado que a sequência possa ser vazia mas é, então trata-se de uma situação excepcional e uma excepção deveria ser lançada de imediato. Neste caso, porque não usar o método Single? Na minha opinião, quando ocorre uma falha deste tipo, é melhor falhar cedo e rápidamente do que tarde e lentamente.

Otros métodos da API LINQ que seguem o mesmo padrão são: ElementAt/ElementAtOrDefault, First/FirstOrDefault and Last/LastOrDefault.

Posted por Paulo Morgado | with no comments
Filed under: , , ,
LINQ With C# (Portuguese)

Já presenciei e estive envolvido em algumas discussões acerca da correcção e utilidade do método Single na API do LINQ.

O argumento mais comum é que se está a pedir o primeiro elemento de um conjunto e que será lançada uma excepção se existir mais que um elemento nesse conjunto. Em vez disso, deveria ser usado o método First.

Apesar da documentação do método Single dizer que retorna um único e específico elemento de um sequência de valores, quando, na verdade, retorna O único e específico elemento de um sequência de UM valor. Quando se usa o método Single está-se a afirmar que a consulta resultará num valor escalar em vez de um conjunto de dimensão arbitrária.

Por outro lado, a documentação do método First diz ue retorna o primeiro elemento de um sequência de dimensão arbitrária.

Imagine que quer apanhar um taxi. Vai a uma fila de taxis e apanha o primeiro (FIRST) da fila, independentemente de quantos lá estiverem.

Por outro lado, se vai a um parque de estacionamento buscar o seu carro, quer o seu específico (SINGLE) carro. Se a sua “consulta” retornar mais de um carro, é uma excepção. Seja porque não reotrnou apenas o seu carro ou porque, por acaso, tinha mais de um carro seu no parque. É qualquer dos casos, é necessário refinar a consulta porque não vai ser possível conduzir mais que um ao mesmo tempo.

Posted por Paulo Morgado | 3 comment(s)
Filed under: , , ,

Quando estou a montar uma solução para uma demonstração, geralmente tenho vários projectos para demonstrar várias funcionalidades.

Quando quere executar um desses projectos, tenho de o configurar como sendo o projecto de arranque (via a opção Set as StartUp Project no menu Project ou no menu de contexto do projecto no Solution Explorer) e executá-lo (em modo de depuração ou não).

Também é possível executar um projecto em modo de depuração a partir do menu de contexto do projecto no Solution Explorer, mas não é possível executá-lo sem ser em modo de depuração.

Enquanto preparo a minha sessão para o próximo Microsoft TechDays 2010, decidi contronar este incómodo criando macros para definir o projecto corrente como o projecto inicial e executá-lo (em modo de depuração ou não):

Sub SetAsStartUpProjectAndStartWithoutDebuggingMacro()
    DTE.ExecuteCommand("Project.SetasStartUpProject")
    DTE.ExecuteCommand("Debug.StartWithoutDebugging")
End Sub

Sub SetAsStartUpProjectAndStartWithDebuggingMacro()
    DTE.ExecuteCommand("Project.SetasStartUpProject")
    DTE.Debugger.Go(False)
End Sub

E ainda é possível atribuír atalhos de teclado a estas macros (Shift+Alt+F5 para executar em modo de depuração e Ctrl+Shift+Alt+F5 para executar sem ser em modo de depuração) assim como botões em barras de ferramentas.

No próximo dia 27 será realizada a 1ª reunião presencial da comunidade NetPonto, no Porto. Para participar, é só efectuar o registo.

O C# 4.0 introduz um novo tipo: dynamic. dynamic é um tipo estático que contorna os mecanismos de verificação estática de tipos.

Este novo tipo é muito útil para interoperar com:

Porque a verificação estática de tipos é contornada, isto:

dynamic dynamicValue = GetValue();
dynamicValue.Method();

é equivalente a isto:

object objectValue = GetValue();
objectValue
    .GetType()
        .InvokeMember(
            "Method",
            BindingFlags.InvokeMethod,
            null,
            objectValue,
            null);

Aparte a memorização “escondida” do call site e alguma resolução dinâmica, dynamic apenas tem melhor aspecto. Qualquer erro de digitação só será descoberto em tempo de execução.

De facto, se estou a escrever o código, eu sei o contrato do que estou a chamar. Não seria bom se o compilador pudesse fazer alguma verificação estática de tipos na interacção com estes objectos dinâmicos?

Imagine-se que o objecto dinâmico que estou a obter na chamada ao método GetValue, alé do método sem parâmetros Method também tem uma propriedade Property do tipo string. Ist quer dizer que, do ponto de vista do código que estou a escrever, o contrato que o objecto dinâmico devolvido por GetValue implementa é:

string Property { get; }
void Method();

Com se trata de um contrato bem definido, eu poderia escrever uma interface para o representar:

interface IValue
{
    string Property { get; }
    void Method();
}

Se dynamic permitisse a especificação do contrato no formato dynamic(contrato), eu poderia escrever isto:

dynamic(IValue) dynamicValue = GetValue();
dynamicValue.Method();

Ist não quer dizer que o valor por GetValue tem de implementar a interface IValue. Apenas permite ao compilador verificar que dynamicValue.Method() é uma utilização válida de dynamicValue e dynamicValue.OtherMethod() não.

Se a interface IValue já existir, por alguma razão, não há qualquer problema. Mas ter de adicionar um novo tipo à assembly apenas para ser usado em tempo de compilação não me parece correcto. Por isso, dynamic podeia ser um novo tipo de especificação de tipos. Algo como:

dynamic DValue
{
    string Property { get; }
    void Method();
}

O código passaria a ser escrito assim;

DValue dynamicValue = GetValue();
dynamicValue.Method();

O compilador nunca geraia qualquer IL ou metadados para esta especificação de tipo. Esta especificação de tipo seria usada apenas para o compilador efectuar uma verificação estática dos objectos diâmicos. Como consequência, não faz qualquer sentido ser acessível publicamente, pelo que tal não seria permitido.

Mais uma vez, se a interface IValue (ou qualquer outra definição de tipo) já existir, pode ser usada na definição de tipo dinâmico:

dynamic DValue : IValue, IEnumerable, SomeClass
{
    string Property { get; }
    void Method();
}

Um benfício acrescido seria IntelliSense.

Tenho recebido reacções mistas em relação a esta proposta. O que acham? Seria algo útil?