【问题标题】:Cap string to a certain length directly without a function不使用函数直接将字符串限制为一定长度
【发布时间】:2017-04-24 05:36:31
【问题描述】:

不与this 重复。

我想让一个字符串有一个最大长度。它不应该超过这个长度。让我们说一个20个字符的长度。如果提供的字符串 > 20,则取前 20 个字符串并丢弃其余字符串。

The 对该问题的回答显示了如何使用函数为字符串加盖,但我想在没有函数的情况下直接执行此操作。我希望每次写入字符串时都进行字符串长度检查。

以下是我不想想做的事情:

string myString = "my long string";
myString = capString(myString, 20); //<-- Don't want to call a function each time

string capString(string strToCap, int strLen)
{
    ...
}

我可以通过一个属性来实现这一点:

const int Max_Length = 20;
private string _userName;

public string userName
{
    get { return _userName; }
    set
    {
        _userName = string.IsNullOrEmpty(value) ? "" : value.Substring(0, Max_Length);
    }
}

然后我可以很容易地使用它来调用一个函数来限制它:

userName = "Programmer";

问题在于,我想限制的每个string 都必须为它们定义多个变量。在这种情况下,_userNameuserName(属性)变量。

有什么聪明的方法可以做到这一点,而无需为每个字符串创建多个变量,同时不必在每次我想修改string 时调用函数?

【问题讨论】:

  • 除了下面的答案之外,您还可以使用 PostSharp 等 AOP 框架来定义拦截您的属性设置器的属性。 PostSharp 有免费/特快版。
  • 感谢您的建议。我正在使用 Unity3D 和 Mono,并试图防止使用会增加二进制大小或导致移动设备出现问题的第三方库。
  • 不知道它是否有效,但 Unity 是否尊重 .NET 内置的 StringLengthAttribute
  • StringLength 来自 System.ComponentModel.DataAnnotations 命名空间。这在 Unity 中不包含或不认可。这是 Unity 在其 .NET 3.5 中未包含的功能之一。

标签: c# unity3d


【解决方案1】:

创建一个具有string 属性的类,并将所有代码放在那里。然后,您可以在任何地方使用s.Value 作为具有所需特征的字符串。

类似:

class Superstring
{
    int max_Length = 20;
    string theString;

    public Superstring() { }
    public Superstring(int maxLength) { max_Length = maxLength; }
    public Superstring(string initialValue) { Value = initialValue; }
    public Superstring(int maxLength, string initialValue) { max_Length = maxLength; Value = initialValue; }

    public string Value { get { return theString; } set { theString = string.IsNullOrEmpty(value) ? value : value.Substring(0, Math.Min(max_Length, value.Length)); } }
}

并使用:

Superstring s = new Superstring("z");
s.Value = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";
string s2 = s.Value;

【讨论】:

  • 希望避免创建另一个包含主字符串的类实例。这是多个步骤,并且会比我的问题中的代码占用更多的内存。将等待看看是否有其他方法。
【解决方案2】:

有趣的情况 - 我建议创建一个struct,然后为它定义一个implicit conversion operator,类似于在this Stack Overflow question 中所做的。

public struct CappedString
{
    int Max_Length;
    string val;

    public CappedString(string str, int maxLength = 20)
    {
        Max_Length = maxLength;
        val = (string.IsNullOrEmpty(str)) ? "" :
              (str.Length <= Max_Length) ? str : str.Substring(0, Max_Length);
    }

    // From string to CappedString
    public static implicit operator CappedString(string str)
    {
        return new CappedString(str);
    }

    // From CappedString to string
    public static implicit operator string(CappedString str)
    {
        return str.val;
    }

    // To making using Debug.Log() more convenient
    public override string ToString()
    {
        return val;
    }

    // Then overload the rest of your operators for other common string operations
}

以后你可以像这样使用它:

// Implicitly convert string to CappedString
CappedString cappedString = "newString";

// Implicitly convert CappedString to string
string normalString = cappedString;

// Initialize with non-default max length
CappedString cappedString30 = new CappedString("newString", 30);

注意:不幸的是,这不是完美的解决方案 - 因为隐式转换没有提供将现有值传输到新实例的方法,任何使用非默认长度值初始化的 CappedString 都需要分配给使用构造函数,否则其长度限制将恢复为默认值。

【讨论】:

  • +1。我比我的答案更喜欢这个。 (我一直在寻找拥有s = "string" 的方法,但没有考虑定义运算符。)干得好!
  • 运算符重载+结构也很棒。
  • 我刚试过。我得到ArgumentOutOfRangeException: startIndex + length &gt; this.length 异常。我认为您应该尝试一下,自己看看
  • @Programmer 你说得对!我只是逐字复制原始代码,但是当字符串短于最大长度时,它看起来像是窒息了。我对其进行了编辑以...制作一个更丑陋的三元组,因此您可能想也可能不想重构。 =P
  • @Bergi 不幸的是后者。由于 C# 不允许赋值运算符的实际重载,这是我能想到的最好的方法。以后需要非默认长度限制的赋值仍然需要显式调用构造函数,而不是依赖隐式转换...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多