это должно помочь: его названное акцентное сгибание:
http://alistapart.com/article/accent-folding-for-auto-complete
ref
говорит компилятору, что объект инициализируется прежде, чем ввести функцию, в то время как out
говорит компилятору, что объект будет инициализирован в функции.
Поэтому, в то время как ref
два пути, out
, является единственным.
необходимо использовать out
в предпочтении везде, где оно достаточно для требований.
"Пекарь"
Поэтому первый изменяет Вашу строковую ссылку для указания "Пекарю". Изменение ссылки возможно, потому что Вы передали его через касательно ключевого слова (=> ссылка на ссылку на строку). Второй вызов получает копию ссылки на строку.
строка смотрит некоторое специальное предложение сначала. Но строка является просто классом ссылки и если Вы определяете
string s = "Able";
тогда s, ссылка на строковый класс, который содержит "Способный" текст! Другое присвоение на ту же переменную через
s = "Baker";
не меняет исходную струну, но просто создает новый экземпляр, и позвольте s указать на тот экземпляр!
можно попробовать его следующим небольшим примером кода:
string s = "Able";
string s2 = s;
s = "Baker";
Console.WriteLine(s2);
, Что Вы ожидаете? То, что Вы получите, все еще в состоянии, потому что Вы просто устанавливаете ссылку в s к другому экземпляру, в то время как s2 указывает на исходный экземпляр.
РЕДАКТИРОВАНИЕ: строка также неизменна, что означает, что нет просто никакого метода или свойства, которое изменяет существующий строковый экземпляр (можно попытаться найти один в документах, но Вы не будете пластины никакой:-)). Все методы обработки строк возвращают новый строковый экземпляр! (Вот почему Вы часто получаете лучшую производительность при использовании класса StringBuilder)
explicit
конструктор.
– AraK
17 December 2010 в 13:11
Так как Вы являетесь передающими в ссылочном типе (класс) нет никакого использования потребности ref
, потому что на значение по умолчанию только ссылка к фактическому объекту передается, и поэтому Вы всегда изменяете объект позади ссылки.
Пример:
public void Foo()
{
MyClass myObject = new MyClass();
myObject.Name = "Dog";
Bar(myObject);
Console.WriteLine(myObject.Name); // Writes "Cat".
}
public void Bar(MyClass someObject)
{
someObject.Name = "Cat";
}
, Поскольку долго Вы передаете в классе, который Вы не должны использовать ref
, если Вы хотите изменить объект в своем методе.
ref
модификатор означает что:
out
модификатор означает что:
А также разрешение Вам повторно присвоить чужую переменную другому экземпляру класса, возвратите несколько значений и т.д., , использование ref
или out
сообщает кому-то еще, в чем Вы нуждаетесь от них и что Вы намереваетесь сделать с переменной, которую они обеспечивают
, Вам не нужно ref
или out
, если все, что Вы собираетесь сделать, изменяют вещи внутренний MyClass
экземпляр, который передается в аргументе someClass
.
someClass.Message = "Hello World"
, используете ли Вы ref
, out
или ничто someClass = new MyClass()
внутренний myFunction(someClass)
выгружает объект, замеченный someClass
в пределах myFunction
метод только. Вызывающий метод все еще знает об исходном MyClass
экземпляре, который он создал и передал Вашему методу Вы потребность ref
или out
, если Вы планируете свопинг someClass
для совершенно нового объекта и хотите вызывающий метод видеть Ваше изменение
someClass = new MyClass()
внутренний myFunction(out someClass)
изменения объект, замеченный методом, который названный myFunction
, И они хотят знать то, что Вы собираетесь сделать с их данными. Предположите запись библиотеки, которой будут пользоваться миллионы разработчиков. Вы хотите, чтобы они знали то, что Вы собираетесь сделать с их переменными, когда они звонят, Ваши методы
Используя [1 123] делает оператор "Передачи переменной присвоенный некоторому значению, когда Вы называете мой метод. Знайте, что я мог бы изменить его для чего-то еще полностью в ходе моего метода. Не ожидайте, что Ваша переменная укажет на старый объект, когда я сделан"
Используя [1 124], делает оператор "Передачи переменной заполнителя к моему методу. Не имеет значения, имеет ли это значение или нет; компилятор вынудит меня присвоить его новому значению. Я абсолютно гарантирую, что объект, на который указывает Ваша переменная перед вызовом моего метода, , будет отличаться к тому времени, когда я сделан
in
модификатор также , И это препятствует тому, чтобы метод выгрузил переданный в экземпляре для другого экземпляра. Думайте это как высказывание тем миллионам разработчиков "передает меня Ваша исходная ссылка на переменную, и я обещаю не выгрузить Ваши тщательно обработанные данные для чего-то еще". in
имеет некоторые особенности и в некоторых случаях такой как, где неявное преобразование могло бы потребоваться, чтобы делать Ваше короткое совместимое с in int
, компилятор временно сделает интервал, расширит Ваше короткое до него, передаст его ссылкой и закончится. Это может сделать это, потому что Вы объявили, что не собираетесь смешивать с ним.
Microsoft сделала это с эти .TryParse
методы на числовых типах:
int i = 98234957;
bool success = int.TryParse("123", out i);
Путем установки флага параметра как [1 129] они активно объявляют здесь, "мы определенно попытка изменить кропотливо обработанное значение 98234957 для чего-то еще"
, Конечно, они отчасти имеют к для вещей как парсинг типов значения, потому что, если бы методу синтаксического анализа не позволили выгрузить тип значения для чего-то еще, это не работало бы очень хорошо.. Но предположите, что был некоторый фиктивный метод в некоторой библиотеке, которую Вы создаете:
public void PoorlyNamedMethod(out SomeClass x)
Вы видите, что это out
, и можно таким образом знать это при пребывании в течение часов, производя подсчеты, создавая идеальный SomeClass:
SomeClass x = SpendHoursMakingMeAPerfectSomeClass();
//now give it to the library
PoorlyNamedMethod(out x);
Хорошо, который был пустой тратой времени, беря все те часы для создания того идеального класса. Это определенно будет отказанным и замененным PoorlyNamedMethod
Для иллюстрирования многих превосходных объяснений я разработал следующее консольное приложение:
using System;
using System.Collections.Generic;
namespace CSharpDemos
{
class Program
{
static void Main(string[] args)
{
List<string> StringList = new List<string> { "Hello" };
List<string> StringListRef = new List<string> { "Hallo" };
AppendWorld(StringList);
Console.WriteLine(StringList[0] + StringList[1]);
HalloWelt(ref StringListRef);
Console.WriteLine(StringListRef[0] + StringListRef[1]);
CiaoMondo(out List<string> StringListOut);
Console.WriteLine(StringListOut[0] + StringListOut[1]);
}
static void AppendWorld(List<string> LiStri)
{
LiStri.Add(" World!");
LiStri = new List<string> { "¡Hola", " Mundo!" };
Console.WriteLine(LiStri[0] + LiStri[1]);
}
static void HalloWelt(ref List<string> LiStriRef)
{ LiStriRef = new List<string> { LiStriRef[0], " Welt!" }; }
static void CiaoMondo(out List<string> LiStriOut)
{ LiStriOut = new List<string> { "Ciao", " Mondo!" }; }
}
}
/*Output:
¡Hola Mundo!
Hello World!
Hallo Welt!
Ciao Mondo!
*/
AppendWorld
: копия StringList
названный LiStri
передается. В начале метода эта копия ссылается на исходный список и поэтому может использоваться для изменения этого списка. Позже LiStri
ссылки другой List<string>
объект в методе, который не влияет на исходный список.
HalloWelt
: LiStriRef
уже псевдоним инициализированный ListStringRef
. Переданный List<string>
объект используется для инициализации нового, поэтому ref
было необходимо.
CiaoMondo
: LiStriOut
псевдоним [1 113] и должен быть инициализирован.
Так, если метод просто изменяет объект, на который ссылается переданная переменная, компилятор не позволит Вам использовать out
, и Вы не должны использовать ref
, потому что это перепутало бы не компилятор, но читателя кода. Если метод сделает ссылку передаваемого аргумента другой объект, используйте ref
для уже инициализированного объекта и out
для методов, которые должны инициализировать новый объект для передаваемого аргумента. Помимо этого, ref
и out
ведут себя то же.
Допустим, Дом появляется в кабинке Питера по поводу меморандума об отчетах TPS.
Если бы Дом был аргументом ref, у него была бы распечатанная копия служебной записки.
Если бы Дом был неприкрытым аргументом, он заставил бы Питера распечатать новую копию служебной записки, чтобы тот взял с собой.
Помните, что эталонный параметр, который передается внутри функция напрямую обрабатывается.
Например,
public class MyClass
{
public string Name { get; set; }
}
public void Foo()
{
MyClass myObject = new MyClass();
myObject.Name = "Dog";
Bar(myObject);
Console.WriteLine(myObject.Name); // Writes "Dog".
}
public void Bar(MyClass someObject)
{
MyClass myTempObject = new MyClass();
myTempObject.Name = "Cat";
someObject = myTempObject;
}
Здесь будет написано «Собака», а не «Кошка». Следовательно, вы должны напрямую работать с someObject.
Пример расширения собаки и кошки. Второй метод с ref изменяет объект, на который ссылается вызывающий объект. Отсюда "Кот" !!!
public static void Foo()
{
MyClass myObject = new MyClass();
myObject.Name = "Dog";
Bar(myObject);
Console.WriteLine(myObject.Name); // Writes "Dog".
Bar(ref myObject);
Console.WriteLine(myObject.Name); // Writes "Cat".
}
public static void Bar(MyClass someObject)
{
MyClass myTempObject = new MyClass();
myTempObject.Name = "Cat";
someObject = myTempObject;
}
public static void Bar(ref MyClass someObject)
{
MyClass myTempObject = new MyClass();
myTempObject.Name = "Cat";
someObject = myTempObject;
}