Matrizes .Net com limite inferior> 0
Pergunta
Embora talvez seja uma coisa bizarra de se fazer, preciso criar um Array em .Net com um limite inferior> 0.A princípio, isso parece ser possível, usando:
Array.CreateInstance(typeof(Object), new int[] {2}, new int[] {9});
Produz os resultados desejados (uma matriz de objetos com um limite inferior definido como 9).No entanto, a instância do array criado não pode mais ser passada para outros métodos esperando Object[]
me dando um erro dizendo que:
System.Object[*]
não pode ser lançado em um System.Object[]
.Qual é essa diferença nos tipos de array e como posso superar isso?
Editar:código de teste =
Object x = Array.CreateInstance(typeof(Object), new int[] {2}, new int[] {9});
Object[] y = (Object[])x;
O que falha com:"Não é possível converter objeto do tipo 'System.Object[*]' para o tipo 'System.Object[]'."
Gostaria também de salientar que esta abordagem FAZ funcionam ao usar múltiplas dimensões:
Object x = Array.CreateInstance(typeof(Object), new int[] {2,2}, new int[] {9,9});
Object[,] y = (Object[,])x;
O que funciona bem.
Solução
Este artigo aqui explica isso: http://www.panopticoncentral.net/2004/03/17/non-zero-lower-bounded-arrays-the-other-side-of-the-coin/
Outras dicas
A razão pela qual você não pode lançar de um para o outro é que isso é mau.
Digamos que você crie um array de object[5..9] e o passe para uma função F como um object[].
Como a função saberia que este é um 5..9?F está esperando um array geral, mas está ficando restrito.Você poderia dizer que é possível saber, mas isso ainda é inesperado e as pessoas não querem fazer todo tipo de verificações de limites sempre que quiserem usar um array simples.
Um array é a estrutura mais simples em programação, torná-lo muito complicado o torna inutilizável.Você provavelmente precisará de outra estrutura.
O que você deve fazer é uma classe que seja uma coleção restrita que imite o comportamento desejado.Dessa forma, todos os usuários dessa classe saberão o que esperar.
class ConstrainedArray<T> : IEnumerable<T> where T : new()
{
public ConstrainedArray(int min, int max)
{
array = new T[max - min];
}
public T this [int index]
{
get { return array[index - Min]; }
set { array[index - Min] = value; }
}
public int Min {get; private set;}
public int Max {get; private set;}
T[] array;
public IEnumerator<T> GetEnumerator()
{
return array.GetEnumarator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return array.GetEnumarator();
}
}
Não sei por que isso não pode ser passado como Object[], mas não seria fácil se você apenas criasse uma classe real para agrupar um array e lidar com sua "lógica estranha" lá?
Você obteria os benefícios de usar um objeto de referência real onde pudesse adicionar "inteligência" à sua classe.
Editar:Como você está lançando seu Array, poderia postar mais algum código?Obrigado.
Basta armazenar seu limite inferior em um número inteiro const offset e subtrair esse valor de tudo o que sua fonte retorna como índice.
Também:este é um recurso antigo do VB6.Acho que pode haver um atributo para ajudar a apoiá-lo.