Как вернуть ссылку на строку в c #? - PullRequest
4 голосов
/ 18 ноября 2008

Я хочу написать такую ​​функцию, как

ref String TestIt( int index )
{
return this.TestArray[index];
};

чтобы я мог написать код вроде:

MyClass.TestIt(0) = "Hello World";

Моя цель - подражать этой декларации c ++

CString& MyClass::Data( UINT index);

По ссылке я имею в виду термин c ++ Адрес переменной.
другими словами после моего звонка в TestIT (0) TestArray [0] будет содержать «Hello World».

EDIT Я не могу использовать индексатор, потому что моя цель - конвертировать файл .cpp в c # на постоянной основе. Чем ближе я могу имитировать этот код C ++, тем меньше конвертера я должен написать.

Ответы [ 7 ]

4 голосов
/ 18 ноября 2008

Для этого вам нужно написать свойство setter. К сожалению, сеттеры не могут принимать дальнейшие аргументы в C #, поэтому вы не сможете написать этот код 1: 1 в C #. Самый близкий вы можете получить вложенный класс со свойством по умолчанию:

class YourClass {
    public class Nested {
        public Nested(YourClass outer) { m_RefToOuterWorld = outer; }
        private readonly YourClass m_RefToOuterWorld;

        public string this[int index] {
            get { return m_RefToOuter.TestArray[index];
            set { m_RefToOuter.TestArray[index] = value; }
        }
    }

    private readonly Nested m_Nested;
    private string[] TestArray = new string[10];

    public YourClass() { m_Nested = new Nested(this); }

    public Nested TestIt { get { return m_Nested; } }
}

Вы можете использовать это так:

var test = new YourClass();
test.TestIt[2] = "Hello world!";

Кстати, поскольку это так много усилий, вы, вероятно, не хотите этого делать. Кроме того, он не чувствует себя очень C # -y. Бесполезная косвенность через вложенный класс здесь не так часто встречается.

2 голосов
/ 18 ноября 2008

Короткий ответ: вы не можете вернуть ссылку на строку переменная , т. Е. Ссылка на ссылку на строку).

Простое решение состоит в том, чтобы избежать такого рода API и требовать от пользователя задавать строку другим способом:

myobj.SetString(0, "Hello, world!");

Если вам действительно нужно представить (как первоклассный объект) ссылку на вашу строковую ссылку, попробуйте что-то вроде этого API:

Interface IStringReference
{
    void SetString(string value);
    string GetString();
}


class MyClass
{
    public IStringReference TestIt()
    {
        ... details left out ;) ...
    }
}

но я думаю, что это заходит слишком далеко, имитируя значения С ++.

1 голос
/ 18 ноября 2008

Я могу рекомендовать следующее растворение

 public class Test
    {
        Dictionary<int,string> str=new Dictionary<int,string>(); 
        public string this[int i]
        {
            get
            {
                return str[i];
            }
            set
            {
                if(!str.ContainsKey(i))
                    str.Add(i,value);
                else
                    str[i] = value;
            }
        }
0 голосов
/ 18 ноября 2008

Все идентичные строки имеют только одну ссылку, независимо от того, сколько раз на нее есть ссылки в коде.

С http://msdn.microsoft.com/en-us/library/system.string.intern.aspx

Общеязыковая среда выполнения хранение строк путем ведения таблицы, называется пул интерна, который содержит отдельная ссылка на каждый уникальный литеральная строка объявлена ​​или создана программно в вашей программе. Следовательно, экземпляр буквального только строка с определенным значением существует один раз в системе.

Например, если вы назначите тот же буквальная строка с несколькими переменными, среда выполнения извлекает то же самое ссылка на буквальную строку из внутренний пул и назначает его каждому переменная.

0 голосов
/ 18 ноября 2008

Зачем беспокоиться о сохранении 2 версий кода одинаковыми? Не проще ли написать управляемую оболочку C ++, которую можно просто использовать из .Net, а затем вызывать соответствующие функции?

0 голосов
/ 18 ноября 2008

Не могли бы вы просто использовать индексатор (анонимное свойство, принимающее параметры)?

private string []storage = new string[10];
public string this[int index]
{
  get
  {
    return storage[index];
  }
  set
  {
    storage[index] = value;
  }
}

и затем вызывается с:

MyClass[0] = "Hello World";

Конечно, у него нет причудливого тега имени "TestIt" ... вам нужен этот тег имени?

Редактировать: Лол, я гуглил "именованные индексаторы C #", и кого я нашел, отвечая на глупые вопросы с отличными ответами в 2005 году? Никто иной, как Джон Скит .

0 голосов
/ 18 ноября 2008

Вам не нужно возвращать ссылку для достижения вашей цели. Строковые типы являются ссылочными типами, но имеют специальную обработку для сравнения. Поэтому, если вы просто вернете строку из TestIt, проверка на равенство выполнит сравнение строк.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...