27

I am bit confused between the below three ways to clear the contents of a textbox. I am working with WPF and found All are working, but I am unable to find the difference.

Can someone please explain to me about it with some examples?

  • txtUserName.Clear();
  • txtUserName.Text = string.Empty;
  • txtUserName.Text = "";
Shadow The GPT Wizard
  • 66,030
  • 26
  • 140
  • 208
Rocky
  • 4,454
  • 14
  • 64
  • 119
  • Wow... never expected so many answers! Rocky can you please review the answers as well? I added bounty as I find it interesting but you can help me choose the best answer. :) – Shadow The GPT Wizard Sep 03 '13 at 07:33
  • @ShadowWizard: well I think syned Answer is good but required some more explanation something like Sheridan answer. Please you to check once and suggest me. – Rocky Sep 03 '13 at 14:14
  • Still got 5 days, you can also comment on answers and indicate if it's useful or not. BTW congrats for [this](http://i.stack.imgur.com/FX38P.png)! ;-) – Shadow The GPT Wizard Sep 03 '13 at 14:16
  • Why do you assume that there *is* a difference? – RBarryYoung Sep 07 '13 at 21:30

10 Answers10

25

If not going really deep:

Clear: remove content from TextBox and may be delete resources allocated with it

    public void Clear()
    {
      using (this.TextSelectionInternal.DeclareChangeBlock())
      {
        this.TextContainer.DeleteContentInternal(this.TextContainer.Start, this.TextContainer.End);
        this.TextSelectionInternal.Select(this.TextContainer.Start, this.TextContainer.Start);
      }
    }

Assigning empty string (because string.Empty and "" are equal) to Text property just assign empty string to attached property TextBox.TextProperty:

public string Text
{
  get
  {
    return (string) this.GetValue(TextBox.TextProperty);
  }
  set
  {
    this.SetValue(TextBox.TextProperty, (object) value);
  }
}
syned
  • 2,201
  • 19
  • 22
  • 3
    Was going the same way, but what happens behind the scenes after `this.SetValue(TextBox.TextProperty, (object) value);`? Think that's the golden key here. – Shadow The GPT Wizard Aug 29 '13 at 13:04
  • Msdn says that it "just" sets dependency property or throw exception http://msdn.microsoft.com/en-us/library/ms597473.aspx – syned Aug 29 '13 at 13:14
  • Yep, but this triggers *something* that eventually cause the text to be assigned to given string, so wonder where's the code for that. – Shadow The GPT Wizard Aug 29 '13 at 13:16
  • I got as far as `protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) {` of the Textbox but all it does is calling `.Remeasure();` or `.Rerender();` of the related TextBoxView instance. – Shadow The GPT Wizard Aug 29 '13 at 13:17
  • I think String.Empty is init once as a constant and "" is not, so slight diff. – Mike Cheel Sep 01 '13 at 21:58
  • Check private method TextBox.OnTextPropertyChanged(System.String, System.String). – Stipo Sep 01 '13 at 22:02
  • Is there a functional difference as well? Isn't the selection cleared when you set the property to empty string? – adrianm Sep 06 '13 at 11:44
19

The Clear() method does more than just remove the text from the TextBox. It deletes all content and resets the text selection and caret as @syned's answer nicely shows.

For the txtUserName.Text = ""; example, the Framework will create an empty string object if one does not already exist in the string pool and set it to the Text property. However, if the string "" has been used already in the application, then the Framework will use this value from the pool.

For the txtUserName.Text = string.Empty; example, the Framework will not create an empty string object, instead referring to an empty string constant, and set this to the Text property.

In performance tests, it has been shown (in the In C#, should I use string.Empty or String.Empty or “”? post) that there really is no useful difference between the latter two examples. Calling the Clear() method is definitely the slowest, but that is clearly because it has other work to do as well as clearing the text. Even so, the difference in performance between the three options is still virtually unnoticeable.

Community
  • 1
  • 1
Sheridan
  • 68,826
  • 24
  • 143
  • 183
4

If you are behind some performance differences or memory leaks, there are not much (just some additional calls to events when setting text instead of using .Clear() )

However, you dont have access to control itself when using MVVM, so only way to clear the text is by setting text to binded property with TextBox.

In standard application, you can do whatever you want (I will prefer using .Clear() method which is designed for this purpose).

Irfan
  • 2,713
  • 3
  • 29
  • 43
3

It appears that it is doing quite some additional stuff, like checking for the origin of the change, bindings, updating caret position and updating/clearing undo. Most of which is likely not needed when assigning an empty string.

/// <summary>
/// Callback for changes to the Text property
/// </summary>
private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    TextBox textBox = (TextBox)d;
    bool inReentrantChange = false;
    int savedCaretIndex = 0;

    if (textBox._isInsideTextContentChange)
    {
        // Ignore property changes that originate from OnTextContainerChanged,
        // unless they contain a different value (indicating that a
        // re-entrant call changed the value)
        if (textBox._newTextValue != DependencyProperty.UnsetValue)
        {
            // OnTextContainerChanged calls
            //      SetCurrentDeferredValue(TextProperty, deferredTextReference)
            // Usually the DeferredTextReference will appear in the new entry
            if (textBox._newTextValue is DeferredTextReference)
            {
                if (e.NewEntry.IsDeferredReference &&
                    e.NewEntry.IsCoercedWithCurrentValue &&
                    e.NewEntry.ModifiedValue.CoercedValue == textBox._newTextValue)
                {
                    return;
                }
            }
            // but if the Text property is data-bound, the deferred reference
            // gets converted to a real string;  during the conversion (in
            // DeferredTextReference.GetValue), the TextBox updates _newTextValue
            // to be the string.
            else if (e.NewEntry.IsExpression)
            {
                object newValue = e.NewEntry.IsCoercedWithCurrentValue
                                    ? e.NewEntry.ModifiedValue.CoercedValue
                                    : e.NewEntry.ModifiedValue.ExpressionValue;
                if (newValue == textBox._newTextValue)
                {
                    return;
                }
            }
        }

        // If we get this far, we're being called re-entrantly with a value
        // different from the one set by OnTextContainerChanged.  We should
        // honor this new value.
        inReentrantChange = true;
        savedCaretIndex = textBox.CaretIndex;
    }

    // CoerceText will have already converted null -> String.Empty,
    // but our default CoerceValueCallback could be overridden by a
    // derived class.  So check again here.
    string newText = (string)e.NewValue;
    if (newText == null)
    {
        newText = String.Empty;
    }

    textBox._isInsideTextContentChange = true;
    try
    {
        using (textBox.TextSelectionInternal.DeclareChangeBlock())
        {
            // Update the text content with new TextProperty value.
            textBox.TextContainer.DeleteContentInternal((TextPointer)textBox.TextContainer.Start, (TextPointer)textBox.TextContainer.End);
            textBox.TextContainer.End.InsertTextInRun(newText);

            // Collapse selection to the beginning of a text box
            textBox.Select(savedCaretIndex, 0);
        }
    }
    finally
    {
        //
        if (!inReentrantChange)
        {
            textBox._isInsideTextContentChange = false;
        }
    }

    // We need to clear undo stack in case when the value comes from
    // databinding or some other expression.
    if (textBox.HasExpression(textBox.LookupEntry(TextBox.TextProperty.GlobalIndex), TextBox.TextProperty))
    {
        UndoManager undoManager = textBox.TextEditor._GetUndoManager();
        if (undoManager != null)
        {
            if (undoManager.IsEnabled)
                undoManager.Clear();
        }
    }
}
Alex
  • 13,024
  • 33
  • 62
1

"" creates an object while String.Empty creates no object. So it is more efficient to use String.Empty.

Refference: String.Empty vs ""

Regarding .Clear() i didnot get better answer then @syned's answer.

Harish Bhatt
  • 584
  • 6
  • 15
  • That is not true. it is not more efficient to use String.Empty. In-lining "" instead of reffering to string.Empty is faster. http://www.dotnetperls.com/string-empty – Thomas Andreè Wang Sep 04 '13 at 06:32
  • @ThomasAndreèLian I agree their may be some situation where `""` is faster then `string.Empty` but as i came to know after looking at link http://forums.asp.net/p/977917/1250790.aspx i still have same opinion as in my above answer and also agree with your comment that there are also some exceptional situations. When it comes to memory utilization then it is better to use `string.Empty`. I think use of `""` or `string.Empty` all depends upon the your requirement and situation you are dealing with in your program. – Harish Bhatt Sep 04 '13 at 06:58
1
txtUserName.Clear();

This code clears the textbox. It will set the Textbox value to ""

txtUserName.Text = string.Empty;

Doesn't create object. This executes faster than txtUserName.Text = "";

txtUserName.Text = "";

Creates object and affects the performance.

Sangram Nandkhile
  • 17,634
  • 19
  • 82
  • 116
Ronak Patel
  • 2,570
  • 17
  • 20
1

Let's go through the commands one by one.

txtUserName.Clear();

The Clear() command assigns the texbox an empty string just like the next example. Source (best explination is given by syned on this point)

txtUserName.Text = string.Empty;

Now the string.Empty the actuall code for it is

static String()
{
    Empty = "";
}

Meaning that you assign the string "" after compile time.

txtUserName.Text = "";

Now here you just assign the "" string directly to the object on compile time.

Small side note txtUserName.Text = ""; is faster than txtUserName.Text = string.Empty; Source

Thomas Andreè Wang
  • 3,379
  • 6
  • 37
  • 53
1

The string.Empty field is an empty string literal. It is slightly different from an empty string literal constant " ". There is a subtle difference—but one that could be significant in some scenarios. It changes the meaning of a program

We use string.Empty and "" in a C# program. The string.Empty field is initialized to "" at runtime by the .NET Framework.

You cannot use string.Empty as a switch case, because it cannot be determined at compile-time by the C# compiler.

Which explain the differences of string.empty and ""

The Clear() method does more than just remove the text from the TextBox. It deletes all content and resets the text selection

Sumeshk
  • 1,980
  • 20
  • 33
1

Well.. 1st a warning, this answer have that potential to be outside of the current consensus of most developers here but here goes :) try to read it till the end.

These two (and even additional one I included) are exactly the same:

txtUserName.Text = "";
txtUserName.Text = string.Empty;
txtUserName.Text = null;

Even if the assembly in debug configuration might come out a bit different, I am positive that in the release mode which is more optimized they will compile to the exact same assembly.

In case they are not coming out the same - this implies a degraded ability of the complier to translate in the most optimal translation the code agenda of this case, or in other words.. in other languages this might come as the same assembly and from an academic vision of it - it should come out as the same assembly. but not every complier care that much of the academic view of things :)

Regarding the third dude txtUserName.Clear() this is a different case, I assume just like you that the inner implementation of this method actually do or simply use one of those three assignments..
(and as others already mentioned it do even more beyond just removing the chars from the text)
However, if you think object oriented - assume someone want to create a special textbox which includes for example more things to clear in it - for him it will be very convenient to have that 'Clear' method to override.. and if you used the clear method - you don't change your code when you change from the basic textbox to that new custom/special texbox.

So to sum it up - if you are to use the control, you should use its methods and that means using that 'Clear()' method will be more suitable when you want to clear it especially if one day in the future you would want to replace that textbox with a custom textbox of your own. so at least grammatically it is the better choice..
But yes, it will inflict performance if all you wanted is simply to remove the characters from the text property..

Here is a small program to test the efficiency of each under WPF.

<Window x:Class="WpfApplication4.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <TextBox Name="txtbx1" Grid.Row="0"/>
    <TextBox Name="txtbx2" Grid.Row="1"/>
    <TextBox Name="txtbx3" Grid.Row="2"/>
    <TextBox Name="txtbx4" Grid.Row="3"/>
</Grid>

using System;
using System.Windows;

namespace WpfApplication4
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DateTime oldTime, newTime;
            TimeSpan delta;

            var iterations = 100000;

            #region Test performance 1

            oldTime = DateTime.Now;
            for (var i = 0; i < iterations; i++)
                txtbx1.Text = "";
            newTime = DateTime.Now;
            delta = newTime - oldTime;
            txtbx1.Text = delta.Milliseconds.ToString();

            #endregion

            #region Test performance 2

            oldTime = DateTime.Now;
            for (var i = 0; i < iterations; i++)
                txtbx2.Text = string.Empty;
            newTime = DateTime.Now;
            delta = newTime - oldTime;
            txtbx2.Text = delta.Milliseconds.ToString();

            #endregion

            #region Test performance 3

            oldTime = DateTime.Now;
            for (var i = 0; i < iterations; i++)
                txtbx3.Text = null;
            newTime = DateTime.Now;
            delta = newTime - oldTime;
            txtbx3.Text = delta.Milliseconds.ToString();

            #endregion

            #region Test performance 4

            oldTime = DateTime.Now;
            for (var i = 0; i < iterations; i++)
                txtbx4.Clear();
            newTime = DateTime.Now;
            delta = newTime - oldTime;
            txtbx4.Text = delta.Milliseconds.ToString();

            #endregion
        }
    }
}

Those were the results I got: 43, 40, 73, 443

And it is consistent - the first two are about the same +/- a mini-second or two, the third is always slightly longer and the last one is definitely longer than all others.

I think that that is as deep as it gets :)

G.Y
  • 6,042
  • 2
  • 37
  • 54
0

Some say String.Empty is faster than "" however String.EMpty is Static member that is initialized to ""

When we call String.Empty the IL makes call to

mscorlib.dll 

IL_0007:  ldsfld     string [mscorlib]System.String::Empty

Whereas for "" it does not

IL_001a:  ldstr      ""

SO logically it would make more sense that "" is more efficient than String.Empty

Rohit
  • 10,056
  • 7
  • 50
  • 82