这三种清除文本框的方法有什么区别

本文关键字:方法 区别 什么 文本 清除 三种 | 更新日期: 2023-09-27 18:29:25

我对以下三种清除文本框内容的方法有点困惑。我正在与WPF合作,发现所有人都在工作,但我找不到区别。

有人能举几个例子向我解释一下吗?

  • txtUserName.Clear();
  • txtUserName.Text = string.Empty;
  • txtUserName.Text = "";

这三种清除文本框的方法有什么区别

如果没有深入:

清除:从TextBox中删除内容,并可能删除分配给的资源

    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);
      }
    }

将空字符串(因为string.empty和"相等)分配给Text属性只需将空字符串分配给附加的属性TextBox.TextProperty:

public string Text
{
  get
  {
    return (string) this.GetValue(TextBox.TextProperty);
  }
  set
  {
    this.SetValue(TextBox.TextProperty, (object) value);
  }
}

Clear()方法不仅仅是从TextBox中删除文本。它删除了所有内容,并重置了文本选择和插入符号,正如@syned的回答所示。

对于txtUserName.Text = "";示例,如果字符串池中不存在空的string对象,则Framework将创建该对象,并将其设置为Text属性。但是,如果字符串""已经在应用程序中使用,那么Framework将使用池中的该值。

对于txtUserName.Text = string.Empty;示例,Framework不会创建一个空的string对象,而是引用一个空字符串常量,并将其设置为Text属性。

在性能测试中,已经表明(在C#中,我应该使用string.Empty还是string.Empty或"?post)后两个例子之间确实没有什么有用的区别。调用Clear()方法肯定是最慢的,但这显然是因为除了清除文本外,它还有其他工作要做。即便如此,这三个选项之间的性能差异实际上仍然不明显。

如果您是一些性能差异或内存泄漏的幕后推手,则没有太多(只是在设置文本而不是使用.Clear()时对事件的一些额外调用)

然而,在使用MVVM时,您无法访问控件本身,所以清除文本的唯一方法是使用TextBox将文本设置为绑定属性。

在标准应用程序中,你可以做任何你想做的事情(我更喜欢使用.Clear()方法,它是为此目的设计的)。

它似乎正在做一些额外的事情,比如检查更改的来源、绑定、更新插入符号位置和更新/清除撤消。当分配一个空字符串时,可能不需要其中的大部分。

/// <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();
        }
    }
}

""创建一个对象,而String.Empty不创建任何对象。因此,使用String.Empty.更有效

参考:String.Empty vs"

关于.Clear(),我没有得到比@syned的答案更好的答案。

让我们逐一查看命令。

txtUserName.Clear();

Clear()命令为文本框指定一个空字符串,就像下一个示例一样。来源(关于这一点,syned给出了最佳解释)

txtUserName.Text = string.Empty;

现在string.Empty的实际代码是

static String()
{
    Empty = "";
}

这意味着您在编译时之后分配字符串"。

txtUserName.Text = "";

现在,您只需在编译时将"字符串直接分配给对象。

小旁注txtUserName.Text = "";txtUserName.Text = string.Empty;源快

txtUserName.Clear();

此代码清除文本框。它会将文本框值设置为"

txtUserName.Text = string.Empty;

不创建对象。这比txtUserName.Text = ""执行得更快;

txtUserName.Text = "";

创建对象并影响性能。

字符串.空字段是一个空字符串文字。它与空字符串文字常量稍有不同"。这是一个微妙的区别,但在某些情况下可能是显著的。它改变了程序的含义

我们在C#程序中使用字符串.Empty和"。字符串。.NET Framework在运行时将空字段初始化为"。

不能使用字符串。由于it cannot be determined at compile-time by the C# compiler. ,因此作为开关箱为空

解释字符串空和"的区别

Clear()方法不仅仅是从TextBox中删除文本。它删除所有内容并重置文本选择

嗯。。首先是一个警告,这个答案有可能超出大多数开发人员目前的共识,但这里是:)试着读到最后。

这两个(甚至我还包括另外一个)完全相同:

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

即使调试配置中的程序集可能会有点不同,我也确信在更优化的发布模式中,它们将编译到完全相同的程序集

如果它们不一样——这意味着编译器以最优化的翻译方式翻译本例代码议程的能力下降,或者换句话说。。在其他语言中,这可能是同一个汇编,从学术角度来看,它应该是同一汇编。但并不是每个编纂者都那么关心学术界对事物的看法:)

关于第三个dude txtUserName.Clear(),这是一个不同的情况,我和你一样假设这个方法的内部实现实际上做了或只是使用了这三个赋值中的一个
(正如其他人已经提到的,它除了从文本中删除字符之外,还做得更多)
然而,如果你认为是面向对象的——假设有人想创建一个特殊的文本框,其中包括例如更多要清除的内容——对他来说,覆盖"清除"方法将非常方便。。如果您使用clear方法,当您从基本文本框更改为新的自定义/特殊文本框时,您不会更改代码。

总之,如果你要使用控件,你应该使用它的方法,这意味着当你想清除它时,使用"Clear()"方法会更合适,尤其是如果将来有一天你想用自己的自定义文本框替换该文本框。所以至少在语法上它是更好的选择
但是,是的,如果你只想从文本属性中删除字符,它会带来性能。。

这里有一个小程序来测试每个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
        }
    }
}

这些是我得到的结果:43,40,73443

它是一致的-前两个大约相同+/-一两秒,第三个总是稍微长一点,最后一个肯定比其他的都长。

我认为这是最深的:)

有人说String.Empty"更快,但String。Empty是初始化为"的静态成员

当我们呼叫String.Empty时,IL呼叫

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

而对于",它不进行

IL_001a:  ldstr      ""

因此,从逻辑上讲,"字符串更有效率。空