sbl*_*lom 14 c# syntax typedef
情况
我有一个类在内部处理许多不同类型的文件路径:一些是本地的,一些是远程的; 一些亲戚,一些绝对.
过去,它的许多方法都将它们作为strings 传递给彼此,但是很难跟踪每种方法所期望的确切路径类型.
理想的修复
所以我们基本上是想typedef四种不同的类型string:RemoteRelative,LocalRelative,RemoteAbsolute,和LocalAbsolute.通过这种方式,静态类型检查器可以帮助开发人员确保他们提供并期望string具有正确的语义.
不幸的string是sealed,在BCL中,所以我们不能通过简单的继承来做到这一点.而且没有简单的typedef,所以我们也不能这样做.
实际修复
我最终创建了四个不同的简单类,每个类都包含一个readonly string.
public struct LocalAbsolutePath {
public readonly string path;
public LocalAbsolutePath(string path) {
this.path = path;
}
}
Run Code Online (Sandbox Code Playgroud)
这大部分都有效,但最终会增加一些不受欢迎的冗长.
问题:我是否忽略了任何自然适合简单C#语法的替代方案?
就像我上面提到的,C风格typedef string LocalAbsolutePath;甚至是F#风格type LocalAbsolutePath = string都是我的梦想.但即使是自定义类的方向步骤也会很棒.
das*_*ght 14
你的解决方案很好.您可以通过添加类型转换来对抗额外的详细程度string,让您可以LocalAbsolutePath在任何地方使用string.
public struct LocalAbsolutePath { // Making it a class would be OK too
private readonly string path; // <<=== It is now private
public LocalAbsolutePath(string path) {
this.path = path;
}
public static implicit operator string(LocalAbsolutePath p) {
return p.path;
}
}
Run Code Online (Sandbox Code Playgroud)
你应该做的是保持你当前的方法为你的路径类型创建四个不同的类(甚至让它们继承相同的基类),这样你就可以限制方法只接收这四个Path对象中的一个.
虽然我觉得它var myPath = new LocalAbsolutePath("path")真的不是那么冗长var myPath = "path",因为它简洁而缺乏它在显性上的弥补,但是如果你真的想要,你可以在你的类和字符串之间实现隐式的转换操作符,并拥有它工作:
public static implicit operator LocalAbsolutePath(string path)
{
return new LocalAbsolutePath(path);
}
Run Code Online (Sandbox Code Playgroud)
现在你可以这样做:
LocalAbsolutePath myPath = "Path String";
Run Code Online (Sandbox Code Playgroud)
我创建了一个名为LikeType的 NuGet 包,它在 C# 类中提供typedef类似行为。
您将这样使用它:
class CustomerId : LikeType<string>
{
public CustomerId(string id) : base(id) { }
}
Run Code Online (Sandbox Code Playgroud)
以下是该类型的行为方式:
void ShowTypeBehavior()
{
var customerId = new CustomerId("cust-001"); // create instance with given backing value
string custIdValue = customerId; // implicit cast from class to backing type, sets 'custIdValue' to "cust-001"
var otherCustomerId = new CustomerId("cust-002");
var areEqual = customerId == otherCustomerId; // false
var areNotEqual = customerId != otherCustomerId; // true
var areEqualUsingMethod = customerId.Equals(otherCustomerId); // false
var customerIdCopy = new CustomerId("cust-001"); // create separate instance with same backing value
var isCopyEqual = customerId == customerIdCopy; // true. Instances are considered equal if their backing values are equal.
}
Run Code Online (Sandbox Code Playgroud)