How to do String.Copy in .net core?
Asked Answered
D

5

14

In porting a .net framework app to .net core app, there are some uses of String.Copy to copy strings. But it looks this method is removed from .net core, so how would you copy a string in .net core app, and as a result, it is not present in uwp too. Does assignment string b = a; in .net core means something different as in .netframework?

The copy is used in this code:

public DataDictionary(DataDictionary src)
        :this()
    {
        this.Messages = src.Messages;
        this.FieldsByName = src.FieldsByName;
        this.FieldsByTag = src.FieldsByTag;
        if (null != src.MajorVersion)
            this.MajorVersion = string.Copy(src.MajorVersion);
        if (null != src.MinorVersion)
            this.MinorVersion = string.Copy(src.MinorVersion);
        if (null != src.Version)
            this.Version = string.Copy(src.Version);
    }
Decentralize answered 20/1, 2017 at 7:35 Comment(8)
Why would you use the Copy method?Emery
No, it means just a reference copy in both cases. Do you know why the app is using String.Copy? It's pretty unusual to need ti, and is generally worse than using = (as it involves creating a copy in a way that is almost always unnecessary).Eisler
Related: What's the use of System.String.Copy in .NET?Rumal
tried new String(a)?Giga
@JonSkeet It's a user defined class with string members, and string.Copy was used in the copy constructor.Decentralize
@SunnyRGupta The constructor String(string) is not present in .net core too. :(Decentralize
That doesn't explain why it's being used. Are you able to ask the original developer? It's possible that they didn't understand that strings are immutable in .NET. If they're really trying to ensure they have separate instances so they can lock on them or something similar, I would try to fix that poor practice...Eisler
Possible duplicate of What's the use of System.String.Copy in .NET?Coles
E
7

Assignment of a string is something else than creating a copy. a = b just sets the reference of both variables to the same memory segment. string.Copy actually copies the string and thus the references are not the same any more.

I doubt however if you need string.Copy. Why would you want to have another reference? I can't think of any common cases you ever want this (unless you are using unmanaged code). Since strings are immutable, you can't just change the contents of the string, so copying is useless in that case.


Given your update with the code that uses string.Copy, I would say it is not useful to use string.Copy. Simple assignments will do if you use DataDictionary in managed code only.

Emery answered 20/1, 2017 at 7:39 Comment(6)
Note that, unlike JavaScript, new String(new char[]{'a'}) == new String(new char[]{'a'}) is still True.Ellita
Due to interning I guess. That is the 'problem' string.Copy solves.Emery
Bear in mind that string overrides == so it's not about interning.Rumal
Ah, of course. Good point @Damien_The_Unbeliever. (As a side question: why does string.Copy not work then?)Emery
Thanks, in the code some members are assigned, some are copied, maybe I will just assign them all and see if any test breaks.Decentralize
The correct answer, as answered by Kyle Stay below is var copiedString = new string(stringToCopy.ToCharArray());. There are valid instances where you want two different string instances of the same value. For example, unit testing code that may manipulate the memory of the string reference. It's rare, but valid.Extravert
M
19

This is not as elegant as string.Copy(), but if you do not want reference equality for whatever reason, consider using:

string copiedString = new string(stringToCopy);
Morphia answered 23/4, 2017 at 12:10 Comment(5)
This was the first search result on Google when search for "string.copy c# .net core". Also, my answer does provider a solution the title question of "How to do String.Copy in .net core?".Morphia
Question itself not about the direct copying, but about the Copy methodIndus
So... I should have asked and then answered my own question?Morphia
Embedded in the "question" is "so how would you copy a string in .net core app". This answers that question. Your downvote is invalid.Phosphorous
This answers the question, should be the accepted answer.Jasik
E
7

Assignment of a string is something else than creating a copy. a = b just sets the reference of both variables to the same memory segment. string.Copy actually copies the string and thus the references are not the same any more.

I doubt however if you need string.Copy. Why would you want to have another reference? I can't think of any common cases you ever want this (unless you are using unmanaged code). Since strings are immutable, you can't just change the contents of the string, so copying is useless in that case.


Given your update with the code that uses string.Copy, I would say it is not useful to use string.Copy. Simple assignments will do if you use DataDictionary in managed code only.

Emery answered 20/1, 2017 at 7:39 Comment(6)
Note that, unlike JavaScript, new String(new char[]{'a'}) == new String(new char[]{'a'}) is still True.Ellita
Due to interning I guess. That is the 'problem' string.Copy solves.Emery
Bear in mind that string overrides == so it's not about interning.Rumal
Ah, of course. Good point @Damien_The_Unbeliever. (As a side question: why does string.Copy not work then?)Emery
Thanks, in the code some members are assigned, some are copied, maybe I will just assign them all and see if any test breaks.Decentralize
The correct answer, as answered by Kyle Stay below is var copiedString = new string(stringToCopy.ToCharArray());. There are valid instances where you want two different string instances of the same value. For example, unit testing code that may manipulate the memory of the string reference. It's rare, but valid.Extravert
R
1
string newstring = $"{oldstring}";
Ramey answered 24/1, 2019 at 18:14 Comment(3)
Please consider explaining your code and how it helps resolve the question.Danyelldanyelle
Copying any object is an inherently dangerous act. Normally when I want a copy of a string, I want an independent copy; one that, if I somehow change it, I don't change the thing I copied from. String interpolation accomplishes this with the least amount of keystrokes.Ramey
I just tested this and the new string was still an object reference match with the old string however string b = $"{a} ".Trim(); did work, but not with the space removed.Interstellar
C
0

String.Copy is not removed in .NET Core ‒ in fact it is in .NET Standard 2.0 and thus available in all common .NET environments.

In .NET Core, this is what it looks like:

[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("This API should not be used to create mutable strings. See https://go.microsoft.com/fwlink/?linkid=2084035 for alternatives.")]
public static unsafe string Copy(string str)
{
   ArgumentNullException.ThrowIfNull(str);

   string result = FastAllocateString(str.Length);

   Buffer.Memmove(
       elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below
       destination: ref result._firstChar,
       source: ref str._firstChar);

   return result;
}

You can see EditorBrowsableState.Never there to detract people from using it, and Obsolete with the explanation. The explanation says:

This API should not be used to create mutable strings. See https://go.microsoft.com/fwlink/?linkid=2084035 for alternatives.

This means that if you are using it to create a character buffer to copy data to, you should not! There are far better alternatives, such as String.Create which gives you a Span<char> to copy the data to.

However, the message implies that you should only worry if you actually use it to create mutable strings. The primary use of the method is to return a copy of str such that (object)str != String.Copy(str). If you need it for this purpose and this purpose alone (maybe you are using it in a ConditionalWeakTable), you are safe to use it.

If you are still unsure, there is this option which guarantees to create a new buffer:

static string Copy(string str)
{
    return String.Create(str.Length, str, static (buffer, s) => s.AsSpan().CopyTo(buffer));
}

Just note that String.Create returns String.Empty if the length is 0, and it could also, theoretically, perform interning of the result before returning it. The current implementation does not go as far, but I could imagine, realistically, that this could be viable for very short lengths, where the buffer could be allocated on the stack first and compared to an internal table in case a previously-created (weakly-referenced) string is available.

Cardie answered 26/7 at 17:27 Comment(0)
Z
0

Do you want to copy a string for good? This will help you to understand what means string copy. While string can't be copied because using assignment (s1 = s2) - it copies the pointer to the memory, and thanks to string interning we just reuse same strings. Strings are immutable. To see what really must happen, here is the code. And this is .net core .net6 for you

string s1 = "abc";
char[] newStringDestination = new char [s1.Length];
s1.CopyTo(0, newStringDestination, 0, newStringDestination.Length);
    
string s2 = new string(newStringDestination);
Console.WriteLine(s2);

you can also do this via string.ToCharArray() and then Array.Copy(...)

Zap answered 26/7 at 17:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.