2010-03-30 7 views
7

Następujący program C++ kompiluje i działa zgodnie z oczekiwaniami:Wskaźniki w języku C# do tworzenia tablicy int?

#include <stdio.h> 

int main(int argc, char* argv[]) 
{ 
    int* test = new int[10]; 

    for (int i = 0; i < 10; i++) 
      test[i] = i * 10; 

    printf("%d \n", test[5]); // 50 
    printf("%d \n", 5[test]); // 50 

    return getchar(); 
} 

Najbliżej C# Prosty przykład mógłbym zrobić na to pytanie brzmi:

using System; 

class Program 
{ 
    unsafe static int Main(string[] args) 
    { 
     // error CS0029: Cannot implicitly convert type 'int[]' to 'int*' 
     int* test = new int[10]; 

     for (int i = 0; i < 10; i++) 
      test[i] = i * 10; 

     Console.WriteLine(test[5]); // 50 
     Console.WriteLine(5[test]); // Error 

     return (int)Console.ReadKey().Key; 
    } 
} 

Więc jak mam zrobić wskaźnik?

+1

zadaj sobie pytanie, dlaczego chcesz manipulować wskaźnikami bezpośrednio w zarządzanym języku. – BlackICE

+8

Ponieważ jestem znudzony: D – y2k

+3

Zredukuj swoją nudę czytając rozdział 18 specyfikacji - dwa razy - zanim spróbujesz napisać niebezpieczny kod w C#. –

Odpowiedz

27

C# nie jest C++ - nie oczekuj tych samych rzeczy do pracy w C#, które działały w C++. Jest to inny język, z pewną inspiracją w składni.

W C++ dostęp do tablicy jest krótką ręką do manipulacji wskaźnikami. Dlatego następujące są takie same:

test[5] 
*(test+5) 
*(5+test) 
5[test] 

Jednak nie jest to prawdą w języku C#. 5[test] nie jest poprawny C#, ponieważ nie ma właściwości indeksatora w System.Int32.

W języku C# bardzo rzadko chcesz radzić sobie ze wskaźnikami. Lepiej po prostu traktując je jako int tablicy bezpośrednio:

int[] test = new int[10]; 

Jeśli naprawdę chcemy mieć do czynienia ze wskaźnikiem matematyki z jakiegoś powodu, trzeba flagą metodę unsafe, i umieścić go w fixed context. Nie byłoby to typowe w języku C# i naprawdę jest prawdopodobnie czymś zupełnie niepotrzebnym.

Jeśli naprawdę chcesz, aby tę pracę, najbliżej można zrobić w C# byłoby:

using System; 

class Program 
{ 
    unsafe static int Main(string[] args) 
    { 
     fixed (int* test = new int[10]) 
     { 

      for (int i = 0; i < 10; i++) 
       test[i] = i * 10; 

      Console.WriteLine(test[5]); // 50 
      Console.WriteLine(*(5+test)); // Works with this syntax 
     } 

     return (int)Console.ReadKey().Key; 
    } 
} 

(Ponownie, jest to naprawdę dziwne, C# - nie coś polecam ...)

+1

Dzięki za dobrze przemyślaną odpowiedź. Próbowałem tylko sprawdzić, czy C# jest w stanie zarządzać pamięcią o tak niskim poziomie. Zasadniczo mówisz, że tego typu indeksowania nie można wykonać? Nie mogę uzyskać niczego do pracy, nawet przy użyciu ustalonego kontekstu. Czy wiesz, czy całkowicie utknęliśmy przy użyciu Int32, czy jest to nawet typ natywny czy abstrakcja? – y2k

+0

@Joshua: Edytowałem swoją odpowiedź, aby pokazać, jak możesz to zrobić - ale naprawdę nie polecam jej –

+0

Na platformach C# działa, System.Int32 jest rodzimym typu int. Ale pod maską int [] znajduje się ten sam blok pamięci, jaki widzisz w C++. Jeśli wykonasz 'test [5]', pod maską CLR wykona kontrolę graniczną, a następnie arytmetykę wskaźnika i dereferencję.W tym przypadku nie tracisz żadnych manipulacji na niskim poziomie. –

5

trzeba przypiąć tablicy za pomocą słowa kluczowego fixed więc nie dostanie przeniesiony przez GC:

fixed (int* test = new int[10]) 
{ 
    // ... 
} 

jednak niebezpieczny kod w C# jest raczej wyjątkiem niż regułą. Chciałbym przetłumaczyć Twój kod C na nieszkodliwy kod C#.

+2

Uwaga: Używanie ustalonych zmiennych nie powinno być wykonywane bez uzasadnionego powodu, ponieważ czyni pracę dla GC trudniejszym ... i możesz zabraknąć pamięci, nawet jeśli nie korzystasz z całej pamięci (defragmentacja pamięci). . – Peter

0

Musisz nauczyć się języka C#. Chociaż istnieją podobieństwa syntaktyczne do C/C++, to - podobnie jak Java - ma zupełnie inne podejście.

W języku C# obiekty zachowują się domyślnie jako odniesienia. Oznacza to, że nie trzeba określać odwołania do wskaźnika (&) i składni dereferencji (*).