根据条件隐藏隐式运算符?
Hide implicit operators based on condition?
可能是个愚蠢的问题,因为答案很可能是否定的;但由于我似乎无法在网上找到记录在案的答案,所以我会在这里提问。我有一个 class 有六个 implicit
转换方法。这样做的原因是我的应用程序中其他地方的动态逻辑得到了简化。
// Just an example for simplicity.
public class Number {
private object val;
public Number(int i) { val = i; }
public Number(long l) { val = l; }
public Number(double d) { val = d; }
public static implicit operator int(Number n) => (int)n.val;
public static implicit operator long(Number n) => (long)n.val;
public static implicit operator double(Number n) => (double)n.val;
}
我想知道是否有一种方法可以隐藏转换(如 throw compiler error 或类似的),基于我示例中 Number
class 的实例化和?如果没有办法隐藏它,是否有办法确保始终使用正确的隐式转换?
我相信一个安全的路线是让 val
成为一个 public
属性 调用 Value
并且只是 return 对象并进行显式转换反而。另外,请注意,我没有对基本类型执行此操作;我试图封装一组相似但没有共同基础的自定义类型 class 我的不幸。
实际上,您定义的 Number
class 的明确目的是绕过编译器并允许隐式转换,这可能是无效的。您告诉编译器 not 检查类型,如果转换无效则允许运行时异常。
试图让编译器提供警告意味着试图让它完全按照你告诉它不要做的事情去做。
从某种意义上说,这与仅使用 object
而不是 Number
没有什么不同。
如果您选择使用 object
,那么编译器将不会帮助您。你放弃了类型安全,这意味着你要以某种方式确保跟踪每个值的来源以及它可以或不能转换成什么,这样你就不会得到运行时错误。
类型安全就是安全。保护 rails 帮助我们避免编写运行时会失败的代码。我建议始终使用它,除非有一个非常重要的理由不这样做,通常是在特定类型无关紧要的情况下。通常是这样。
这是另一种看待它的方式:如果要隐式转换为的各种类型没有共性,那么将实例传递给可能使用也可能不使用它的方法没有任何好处。
另一方面,假设存在共性。例如,您的每个基础类型都有一个 属性 和 returns 一个字符串,但是每个类型的 属性 是不同的。在那种情况下,您可以创建一个界面,如下所示:
public interface IHasMyStringProperty
{
string GetTheString { get; }
}
然后,为不同的 classes 创建一个包装器,像这样:
public class Foo
{
public string FooString { get; }
}
public class FooWrapper : IHasMyStringProperty
{
private readonly Foo _foo;
public FooWrapper(Foo foo)
{
_foo = foo;
}
public string GetTheString => _foo.FooString;
}
请注意,我们不会更新 Foo
class 来实现接口,尽管这也可能是一个选项。相反,我们正在创建一个通用接口并创建包装器(或适配器)以使各种类型适应该通用接口。 (您可以同时拥有实现接口的 classes 和需要包装器的 classes。)结果是类型安全。我们将所有其他方法编写为仅适用于 IHasMyStringProperty
。如果我们想传递一些其他类型,我们只需要定义一个实现该接口的包装器。
可能是个愚蠢的问题,因为答案很可能是否定的;但由于我似乎无法在网上找到记录在案的答案,所以我会在这里提问。我有一个 class 有六个 implicit
转换方法。这样做的原因是我的应用程序中其他地方的动态逻辑得到了简化。
// Just an example for simplicity.
public class Number {
private object val;
public Number(int i) { val = i; }
public Number(long l) { val = l; }
public Number(double d) { val = d; }
public static implicit operator int(Number n) => (int)n.val;
public static implicit operator long(Number n) => (long)n.val;
public static implicit operator double(Number n) => (double)n.val;
}
我想知道是否有一种方法可以隐藏转换(如 throw compiler error 或类似的),基于我示例中 Number
class 的实例化和?如果没有办法隐藏它,是否有办法确保始终使用正确的隐式转换?
我相信一个安全的路线是让 val
成为一个 public
属性 调用 Value
并且只是 return 对象并进行显式转换反而。另外,请注意,我没有对基本类型执行此操作;我试图封装一组相似但没有共同基础的自定义类型 class 我的不幸。
实际上,您定义的 Number
class 的明确目的是绕过编译器并允许隐式转换,这可能是无效的。您告诉编译器 not 检查类型,如果转换无效则允许运行时异常。
试图让编译器提供警告意味着试图让它完全按照你告诉它不要做的事情去做。
从某种意义上说,这与仅使用 object
而不是 Number
没有什么不同。
如果您选择使用 object
,那么编译器将不会帮助您。你放弃了类型安全,这意味着你要以某种方式确保跟踪每个值的来源以及它可以或不能转换成什么,这样你就不会得到运行时错误。
类型安全就是安全。保护 rails 帮助我们避免编写运行时会失败的代码。我建议始终使用它,除非有一个非常重要的理由不这样做,通常是在特定类型无关紧要的情况下。通常是这样。
这是另一种看待它的方式:如果要隐式转换为的各种类型没有共性,那么将实例传递给可能使用也可能不使用它的方法没有任何好处。
另一方面,假设存在共性。例如,您的每个基础类型都有一个 属性 和 returns 一个字符串,但是每个类型的 属性 是不同的。在那种情况下,您可以创建一个界面,如下所示:
public interface IHasMyStringProperty
{
string GetTheString { get; }
}
然后,为不同的 classes 创建一个包装器,像这样:
public class Foo
{
public string FooString { get; }
}
public class FooWrapper : IHasMyStringProperty
{
private readonly Foo _foo;
public FooWrapper(Foo foo)
{
_foo = foo;
}
public string GetTheString => _foo.FooString;
}
请注意,我们不会更新 Foo
class 来实现接口,尽管这也可能是一个选项。相反,我们正在创建一个通用接口并创建包装器(或适配器)以使各种类型适应该通用接口。 (您可以同时拥有实现接口的 classes 和需要包装器的 classes。)结果是类型安全。我们将所有其他方法编写为仅适用于 IHasMyStringProperty
。如果我们想传递一些其他类型,我们只需要定义一个实现该接口的包装器。