Pergunta

Eu só fiz uma rotina de troca em C # como este:

static void Swap(ref int x, ref int y)
{
    int temp = x;
    x = y;
    y = temp;
}

Ele faz a mesma coisa que o código neste C ++ faz:

void swap(int *d1, int *d2)
{
    int temp=*d1;
    *d1=*d2;
    *d2=temp;
}

Assim são as ref e out palavras-chave como ponteiros para C # sem usar código unsafe?

Foi útil?

Solução

Eles estão mais limitados. Você pode dizer ++ em um ponteiro, mas não em um ref ou out.


Editar Alguma confusão nos comentários, para ser absolutamente claro: a questão aqui é para comparar com as capacidades de ponteiros. Você não pode executar a mesma operação que ptr++ em um ref / out, ou seja, torná-lo resolver um local adjacente na memória. É verdade (mas irrelevante aqui) que você pode executar o equivalente a (*ptr)++, mas isso seria para compará-lo com os recursos do valores , não ponteiros.


É uma aposta segura que eles são internamente apenas ponteiros, porque a pilha não se moveu e C # é cuidadosamente organizado de modo que ref e out sempre se referem a uma região ativa da pilha.


Editar Para ser absolutamente claro novamente (se ele já não estivesse claro desde o exemplo abaixo), o ponto aqui não é que ref / out pode única ponto para a pilha. -Se que quando que aponta para a pilha, é garantido pelo regime linguístico não se tornar um apontador pendente. Esta garantia é necessário (e relevante / interessante aqui) porque a pilha apenas devoluções informações de acordo com saídas chamada de método, sem verificações para garantir que quaisquer referências ainda existem.

Por outro lado, quando ref / out refere-se a objetos no GC pilha não é nenhuma surpresa que esses objetos são capazes de ser mantido vivo enquanto for necessário: a pilha GC foi concebido precisamente com o objectivo de objetos de retenção por qualquer período de tempo necessário por suas referências, e fornece fixando (ver exemplo abaixo) para apoiar a situações em que o objecto não tem de ser movida por GC compactação.


Se você nunca jogar com interoperabilidade em código inseguro, você vai achar que ref está intimamente relacionada com ponteiros. Por exemplo, se uma interface COM é declarada como este:

HRESULT Write(BYTE *pBuffer, UINT size);

A interoperabilidade montagem vai transformá-lo no seguinte:

void Write(ref byte pBuffer, uint size);

E você pode fazer isso de chamá-lo (eu acredito que a interoperabilidade coisas cuida prendendo a matriz):

byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);

Em outras palavras, ref para o primeiro byte você obtém acesso a todos; que é, aparentemente, um ponteiro para o primeiro byte.

Outras dicas

parâmetros de referência em C # pode ser usado para substituir um uso de ponteiros, sim. Mas não todos.

Outra utilização comum para os ponteiros é como um meio para a iteração através de uma matriz. Out / ref parâmetros não pode fazer isso, então não, eles não são "o mesmo que os ponteiros".

ref e out são usados ??somente com os argumentos da função para significar que o argumento deve ser passado por referência em vez do valor. Neste sentido, sim, eles são um pouco como ponteiros em C ++ (mais como referências na verdade). Leia mais sobre isso em este artigo .

Na verdade, eu compará-los com referências C ++ em vez de ponteiros. Ponteiros, em C ++ e C, são um conceito mais geral, e referências irá fazer o que quiser.

Todos estes são, sem dúvida, os ponteiros sob as cobertas, é claro.

A coisa agradável sobre o uso de a é que você tem a garantia de que o item será atribuído um valor -. Você receberá um erro de compilação se não

Embora as comparações estão no olho de quem vê ... Eu não digo. 'Ref' muda o convenção de chamada , mas não o tipo dos parâmetros. Em seu C ++ exemplo, D1 e D2 são do tipo int *. Em C # eles ainda são Int32 de, eles só acontecerá a ser passados ??por referência em vez de por valor.

A propósito, o seu código C ++ realmente não trocar suas entradas no sentido tradicional. Generalizando-o assim:

template<typename T>
void swap(T *d1, T *d2)
{
    T temp = *d1;
    *d1 = *d2;
    *d2 = temp;
}

... não vai funcionar a menos que todos os tipos de T têm construtores de cópia, e mesmo assim será muito mais ineficiente do que trocar os ponteiros.

A resposta curta é sim (funcionalidade semelhante, mas não exatamente o mesmo mecanismo). Como uma nota lateral, se você usar FxCop para analisar seu código, usando out e ref irá resultar em um erro de "Microsoft.Design" de "CA1045:. DoNotPassTypesByReference"

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top