背景
我有一个原型类TypedString<T>
,旨在对某个特定类别的字符串进行"强类型"(含糊的意义)处理。它使用了C#中类似于奇异递归模板模式(CRTP)的技术。
class TypedString<T>
public abstract class TypedString<T>
: IComparable<T>
, IEquatable<T>
where T : TypedString<T>
{
public string Value { get; private set; }
protected virtual StringComparison ComparisonType
{
get { return StringComparison.Ordinal; }
}
protected TypedString(string value)
{
if (value == null)
throw new ArgumentNullException("value");
this.Value = Parse(value);
}
//May throw FormatException
protected virtual string Parse(string value)
{
return value;
}
public int CompareTo(T other)
{
return string.Compare(this.Value, other.Value, ComparisonType);
}
public bool Equals(T other)
{
return string.Equals(this.Value, other.Value, ComparisonType);
}
public override bool Equals(object obj)
{
return obj is T && Equals(obj as T);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public override string ToString()
{
return Value;
}
}
TypedString<T>
类现在可用于消除在项目中定义一堆不同"字符串类型"时的代码重复。一个简单的示例是在定义Username
类时使用这个类:
class Username
(示例)
public class Username : TypedString<Username>
{
public Username(string value)
: base(value)
{
}
protected override string Parse(string value)
{
if (!value.Any())
throw new FormatException("Username must contain at least one character.");
if (!value.All(char.IsLetterOrDigit))
throw new FormatException("Username may only contain letters and digits.");
return value;
}
}
现在我可以在整个项目中使用Username
类,无需检查用户名是否格式正确 - 如果我有一个类型为Username
的表达式或变量,它是保证正确的(或为空)。
场景1
string GetUserRootDirectory(Username user)
{
if (user == null)
throw new ArgumentNullException("user");
return Path.Combine(UsersDirectory, user.ToString());
}
我不必担心用户字符串的格式 - 我已经知道由于它的类型而是正确的。
情景2
IEnumerable<Username> GetFriends(Username user)
{
//...
}
在这里,调用方仅基于类型就知道返回的内容。一个
IEnumerable<string>
需要查看方法或文档的详细信息。更糟糕的是,如果有人更改了 GetFriends
的实现,例如引入错误并生成无效的用户名字符串,那么该错误可能会悄悄地传播到方法的调用者,并造成各种混乱。这种很好的类型化版本可以防止这种情况发生。
场景三
System.Uri
是 .NET 中的一个类的示例,它几乎只是包装了一个具有大量格式约束和有用部分的帮助属性/方法的字符串。因此,这是这种方法不完全疯狂的证据之一。
问题
我想象中已经有人做过这种事情了。我已经看到了这种方法的好处,不需要再说服自己了。
我可能忽略了什么缺点?
这种方法是否会在以后反噬我?
UserName
被正确编写,TypedString<UserName>
或UserName
类在功能上可以是相同的--TypedString
只是为您提供了一个强制继承模式。 - Hogan