2017-01-23 15 views
0

Я нашел некоторый код в нашем приложении, который проходит через List<T> по ссылке, чтобы указать, что модифицируется:Pass ссылка типа по ссылке, чтобы указать, будет изменен

void DoSomething(ref List<MyType> theList) 
{ 
    theList.Add(new MyType()); 
} 

Я думаю, ясно, что rEF- ключевое слово устарело в этом случае, так как мы могли бы также добавить новые элементы в список без ключевого слова. Однако это указывает на то, что мы модифицируем списки или, по крайней мере, его элементы. Я считаю, что это особенно полезно, если у вас много параметров и вы хотите увидеть, какие из них были изменены и которые просто переданы как значения для выполнения задания.

Вопрос, если это нормально, безусловно, основано на мнениях и будет недействительным для SO, я скорее спрошу, есть ли другой подход к достижению этого или если я даже должен заботиться об этом.

EDIT: Чтобы уточнить мой вопрос. Этот вопрос равен не, если список изменен, это был всего лишь пример. В качестве альтернативы я также использовал любой другой ссылочный тип, а не только List<T>.

+0

Вы ищете эквивалент C++ 'const' для параметров? –

+0

@ BernhardHiller Я сомневаюсь, поэтому я хочу указать, что параметр * изменен * в моем методе, а не наоборот. – HimBromBeere

+1

В C# нет эквивалента для модификаторов констант C++. Этот эффект достигается благодаря реализации интерфейса и ограничениям внутри оберток. – eocron

ответ

5

Однако это означает, что мы меняем список.

Нет, это не так. Он указывает, что ссылка может быть изменена. С помощью ключевого слова ref как «идентификатор» что-то может измениться, по-моему, плохо, так как он открывает двери, которые вы, возможно, не захотите.

Я бы посоветовал изучить аспектно-ориентированное программирование, могли ли вы назначать атрибуты параметрам метода. Из нового компилятора Roslyn с его службами анализа кода вы можете даже проверить, не нарушает ли код основной данные.

+0

Опираясь на атрибуты может быть вариант, однако, я полагаю, поскольку наша команда не использует этот компилятор, альтернативный подход состоит в том, чтобы просто полагаться на API-документ метода. – HimBromBeere

+0

Это возможно. Roslyn используется VS 2015, поэтому вполне возможно, что вы уже используете его. –

+0

Мы фактически используем VS2010 :) – HimBromBeere

-2

Это намного проще и шире, чтобы читать интерфейс , чем смотреть референт и считать его меняющейся коллекцией.

Например, если вы хотите быть постоянным:

public DoSomething<T>(IReadOnlyCollection<T> collection) 
{ 
    //.... 
} 

непостоянным:

public DoSomething<T>(List<T> collection) 
{ 
    //.... 
} 

В случае типа значения это действительно, как вы уточнить ваш вопрос:

Постоянная ссылка:

public DoSomething(int value) 
{ 
    //.... 
} 

непостоянный:

public DoSomething(ref int value) 
{ 
    //.... 
} 

Или, если у вас есть тип без доступа к коду, например, поток:

public class StreamWrapper 
{ 
    private Stream _instance; 

    //now you can specify read or edit methods here and use this class in invokation. 
} 
+1

Список - это всего лишь один пример. Существует несколько типов, которые не поддерживают этот интерфейс. Для 'List ' это хороший вариант. –

+0

@PatrickHofman Благодаря очистке это был всего лишь пример. Разумеется, может быть любой произвольный тип, переданный методу. – HimBromBeere

+0

Почему все ниспровергают, не споря? – eocron

0

Patrick приводит меня к альтернативному пути, который не полагается на атрибуты, поэтому мы можем использовать его в устаревшем коде на машинах со старым компилятором. Мы можем, конечно, написать API-документ appropritely, чтобы указать, что метод изменяет переданный параметр:

/// <summary/> 
/// <param name="theList">list to be modified</param> 
void DoSomething(List<MyType> theList) 

Я думаю, это лучше, так как он это не распространяется полагаться на whrong использование ключевого слова. Однако он предполагает, что клиенты нашего API внимательно прочитают документы.