2017-02-04 6 views
2

(Прежде всего, извините за мой плохой английский)
Вызов по ссылке не работает в C# при замене

Я пытался сделать Poker Card Game.
Как указано ниже. Эти функции перетасовывают колоду,
Кажется, что вызов по ссылке, но, в конце концов, он не работает.

private void disorderCards(PokerCardItem[] cardArray) 
    { 
     Random random = new Random(); 
     for (int t = 0; t < 10; t ++) 
      for (int i = 0; i < cardArray.Length; i ++) 
       swapTwoCards(cardArray[i], cardArray[random.Next() % cardArray.Length]); 
    } 

private void swapTwoCards(PokerCardItem cardA , PokerCardItem cardB) 
    { 
     PokerCardItem temp = cardA; 
     cardA = cardB; 
     cardB = temp; 
    } 

, но если я пишу, как это, он получает работу:

private void disorderCards(PokerCardItem[] cardArray) 
    { 
     Random random = new Random(); 
     for (int i = 0; i < cardArray.Length; i ++) 
     { 
      int n = random.Next() % cardArray.Length; 
      PokerCardItem temp = cardArray[i]; 
      cardArray[i] = cardArray[n]; 
      cardArray[n] = temp; 
     } 
    } 

Что происходит ?? Спасибо!

+0

C# передает аргументы по значению по умолчанию. Если вы хотите передать их по ссылке, вам нужно прямо сказать это с ключевыми словами 'ref' или' out'. – InBetween

ответ

4

Вы должны предварять аргументы типа с ключевым словом: ref

private void swapTwoCards(ref PokerCardItem cardA, ref PokerCardItem cardB) 
{ 
    PokerCardItem temp = cardA; 
    cardA = cardB; 
    cardB = temp; 
} 

Если вы не сделаете это, вы просто передать копию соответствующих ссылок при вызове метода, как показано ниже:

swapTwoCards(cardArray[i], cardArray[random.Next() % cardArray.Length]); 

Вы можете действовать только по свойствам объектов, которые вы проходите. Вы не можете изменить ссылку, которую cardA указывает на или cardB указывает на.

Принимая во внимание ключевое слово ref, вы можете достичь того, что хотите.

Кроме, вы должны сделать выше вызова, как показано ниже:

swapTwoCards(ref cardArray[i], ref cardArray[random.Next() % cardArray.Length]); 

Теперь вы передаете значений по ссылке и вы можете изменить фактические ссылки, которая является то, что вы на самом деле в тело вашего метода.

Для дальнейшего чтения, пожалуйста, посмотрите here.

0

вызывать в параметрах метода вы не передаете ссылку только значения, поэтому, если значение изменяется в пределах метода, ваша фактическая ссылка не будет затронута. вы можете использовать параметры ref/out, если хотите, чтобы они работали.

-1

Возможно, вы слышали, что объекты передаются по ссылке как по умолчанию, и это правда. Однако вам не нужно проходить по ссылке; вам нужно передать ссылку на ссылку, потому что точка swapTwoCards не обновляет объект, а обновляет ссылку на объект.

Чтобы передать ссылку на объект по ссылке, используйте ключевое слово ref.

+0

Эта терминология вводит в заблуждение. По умолчанию все передается по значению, за исключением случаев, когда вы произносите 'ref' или' out' при его передаче, тогда это будет ссылка. __Пассирование по значению__ означает копирование значения выражения и передачу этой копии. «Значение» типа значения - это весь экземпляр, т. Е. Набор всех нестатических полей типа значения, взятых в целом. «Значение» ссылочного типа является ссылкой. Таким образом, передача ссылочного типа по значению означает копирование ссылки, так что теперь у вас есть _two_ ссылки на один и тот же объект. __Пассирование по ссылке__ означает использование одного и того же места хранения. –

+0

Я прочитал проблему OP и думаю, что он читал традиционное объяснение и запутался (почему еще он думал, что «swapTwoCards» будет работать?) Иногда лучше объяснять вещи по-другому, чем повторять то, что уже доказано неправильно поняли, и я видел, как свет продолжается для людей, когда я указываю на двойную косвенность. –

0

По умолчанию аргументы в C# передаются по значению. «Значение» для ссылочных типов - это ссылочный, прозрачный «указатель», который используется для определения фактических данных. В swapTwoCards вы просто меняете указатели вокруг параметров, это не влияет на внешний метод.Вы хотите поменять местами содержимое двух переменных, и для этого есть ref ключевое слово:

private void swapTwoCards(ref PokerCardItem cardA, ref PokerCardItem cardB) 
{ 
    PokerCardItem temp = cardA; 
    cardA = cardB; 
    cardB = temp; 
} 

Украшенные таким образом, аргументы передаются по ссылке на фактических переменных, содержащих значения, и поэтому задания модифицируют исходные переменные. Используйте так:

swapTwoCards(ref cardArray[i], ref cardArray[random.Next() % cardArray.Length]); 

Если у вас есть проблемы, определяющие ли ставить ref в параметрах, попытайтесь представить себе типы параметров быть int или другой тип примитива. Просто помните, что аргументы по умолчанию по умолчанию, и поэтому вы только переключаете значения внутри метода. Типы ссылок и передача аргументов by-ref не имеют ничего общего (ну, конечно, кроме «ссылки», конечно).

 Смежные вопросы

  • Нет связанных вопросов^_^