2008-11-17 4 views
4

Я ищу, чтобы написать функцию, какКак вернуть ссылку на строку в C#?

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

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

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

Моя цель состоит в том, чтобы имитировать эту гр декларации

CString& MyClass::Data(UINT index); 

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

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

ответ

4

Для этого вам необходимо написать свойство сеттера. К сожалению, сеттеры не могут принимать дополнительные аргументы в 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. Бесполезная индивидуализация через вложенный класс здесь не то, что вы увидите очень часто.

+0

Основываясь на моем фоне VB, я начал писать для него простое индексированное свойство, вроде как. Затем я обнаружил, что, хотя VB.Net поддерживает это из коробки, C# требует создания целого нового класса. Облом. – 2008-11-17 21:21:41

+0

Bummer действительно. Если честно, мне никогда не нужна эта особенность VB. В основном это используется для эмуляции семантики неявного оператора CType, так что мы можем использовать это вместо этого. – 2008-11-17 22:57:01

0

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

+0

Это не попытка сравнения строк - это попытка быть заданием, которое поэтому не будет работать. – 2008-11-17 21:24:25

2

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

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

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

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

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


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

, но я думаю, что это будет слишком далеко имитируя lvalues ​​C++ 's.

0

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

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

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

MyClass[0] = "Hello World"; 

Конечно, это не фантазии «TestIt» имя тега ... вам нужно что имя тега?

Редактировать: Lol, я googled для «C# с именем индексаторов», и кто я нашел ответ на глупые вопросы с отличными ответами в 2005 году? Ничего кроме Jon Skeet.

+0

К вашему редактированию: это неудивительно, потому что вы можете использовать Google * любой * поисковый запрос, содержащий «C#», и найти (отличный) ответ Джона. Человек, этот парень такой скучный и предсказуемый. – 2008-11-17 22:59:31

1

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

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

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

+0

Мне нужна бизнес-логика на постоянной основе, у меня уже есть это в сборке смешанного режима, но MFC иногда забавна, и мне бы хотелось, чтобы на моем сервере обеспечивался 100% -ный управляемый код. – 2008-11-17 23:24:13

0

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

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

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

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

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