You are currently browsing the category archive for the 'Genéricos' category.

Hoje a ler a revista MSDN online reparei num artigo que fala sobre implementar I/O assíncrono usando delegados para os callbacks. Imediatamente lembrei-me do projecto que fiz na Inosat, em que para conseguir rede, GPS ou GRPS no dispositivo móvel, usei um sistema parecido com este.

A maior diferença é que, em vez de declarar dois métodos para callback – um em caso de sucesso e outro em caso de falha – usei apenas um, retornando sempre um valor do tipo Result<T>. Por exemplo, se virem no artigo, o autor para o método:

   1: public static string ReadAllText(string path);

define a seguinte assinatura:

   1: public static void ReadAllTextAsync(string path, Action<string> success, Action<Exception> failure);

em que o primeiro método é chamado se o método correr como esperado, o segundo é invocado se houver algum problema pelo caminho. No meu caso, a definição seria algo como:

   1: public static void ReadAllTextAsync(string path, Result<string> success);

em que a classe Result é:

   1: public class Result<T>
   2: {
   3:     private readonly T _value;
   4:     private readonly bool _valid;
   5:     private readonly string _error;
   6:  
   7:     private Result(T value)
   8:     {
   9:         _value = value;
  10:         _valid = true;
  11:     }
  12:  
  13:     private Result(string error) : this()
  14:     {
  15:         _error = error;
  16:     }
  17:  
  18:     private Result()
  19:     {
  20:         _valid = false;
  21:     }
  22:  
  23:     public static Result<T> Failed()
  24:     {
  25:         return new Result<T>();
  26:     }
  27:  
  28:     public static Result<T> Failed(string error)
  29:     {
  30:         return new Result<T>(error);
  31:     }
  32:  
  33:     public static Result<T> Success(T value)
  34:     {
  35:         return new Result<T>(value);
  36:     }
  37:  
  38:     public T Value
  39:     {
  40:         get { return _value; }
  41:     }
  42:  
  43:     public bool Valid
  44:     {
  45:         get { return _valid; }
  46:     }
  47:  
  48:     public string Error
  49:     {
  50:         get { return _error; }
  51:     }
  52: }

Isto permite que o Result seja usado para notificar se o método teve sucesso ou não e, caso não tenha, que se possa passar o erro que se encontrou.

A diferença que encontro nas duas abordagens é que, no meu caso, quem trata do resultado tem de verificar se a operação teve sucesso chamando o result.Valid. No caso da implementação que está na revista, cada método sabe se o resultado teve sucesso ou não. Para os puristas que defendem a abolição do uso de If’s (já trabalhei com alguns ;) ), isto é puro ouro!

Se isto funciona:

IList<FileInfo> list = new List<FileInfo>();
IList<List<FileInfo>> listOfList = new List<List<FileInfo>>();

Porque é que isto tem de dar erro?

IList<IList<FileInfo>> listOfGenericList = new List<List<FileInfo>>();
Cannot implicitly convert type ‘System.Collections.Generic.List<System.Collections.Generic.List<FileInfo>>’ to ‘System.Collections.Generic.IList<System.Collections.Generic.IList<FileInfo>>’. An explicit conversion exists (are you missing a cast?)

Apesar de saber que isto é algo que acontece por desenho da linguagem… Não percebo porque raio é que o cast não funciona, nem mesmo quando o fazemos explicitamente. Será que alguém me pode explicar como se eu fosse uma criança de 5 anos?

Fica para referência futura um belo post sobre genéricos em .Net e em Java, em que o Jonathan Pryor passa pelas mais variadas funcionalidades dos genéricos.  

link: http://www.jprl.com/Blog/archive/development/2007/Aug-31.html

 Perfeito para rever a sintaxe.

View João Caxaria's profile on LinkedIn