Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对运算符重载感到困惑吗_C#_Operator Overloading - Fatal编程技术网

C# 对运算符重载感到困惑吗

C# 对运算符重载感到困惑吗,c#,operator-overloading,C#,Operator Overloading,当我在学习我的小数学库时,我遇到了C#和.NET框架的某些方面,我在理解这些方面遇到了一些困难 这次是运算符重载,特别是术语重载本身。为什么称之为重载?默认情况下,所有对象是否都有所有运算符的实现?即是: public static object operator +(object o1, object o2) 不知何故?如果是这样,为什么如果我尝试o1+o2我会得到编译时错误运算符“+”不能应用于“object”和“object”类型的操作数?这在某种程度上意味着默认情况下对象没有预定义的操

当我在学习我的小数学库时,我遇到了C#和.NET框架的某些方面,我在理解这些方面遇到了一些困难

这次是运算符重载,特别是术语重载本身。为什么称之为重载?默认情况下,所有对象是否都有所有运算符的实现?即是:

public static object operator +(object o1, object o2)
不知何故?如果是这样,为什么如果我尝试
o1+o2
我会得到编译时错误
运算符“+”不能应用于“object”和“object”类型的操作数
?这在某种程度上意味着默认情况下对象没有预定义的操作符,那么术语重载是怎么来的呢

我问这个问题,因为在我的数学库中,使用3D几何元素,我有以下结构:
向量
。现在,我想在内部允许以下构造创建向量:

static Vector operator -(Point p1, Point p2) {...}
由于这在数学上不是100%正确的,但在内部对减少代码混乱非常有用,因此我不想公开此运算符,因此我最初的意图只是:

internal static Vector operator -(Point p1, Point p2) {...}
令人惊讶的是(对我来说)我得到了以下编译时错误:
用户定义操作符'Geometry.operator+(Geometry.Vector,Geometry.Vector)'必须声明为静态和公共的

现在,所有运营商必须公开的限制似乎对运营商的整个过载方面有一定的意义,但似乎有点不一致:

  • 默认情况下,对象没有预定义的运算符:如果事先没有明确定义
    +
    运算符,我无法在默认情况下执行
    object+object
    ,或者执行
    myTpye+myType
  • 定义运算符并不是说创建运算符,而是说重载(对我来说)与第1点不一致
  • 您不能限制
    操作符的访问修饰符,它们必须是
    公共的
    ,考虑到第1点,这是没有意义的。但考虑到第2点,这有点意义
  • 有人能简单地解释一下我把这一切搞得一团糟吗

  • 您不能执行
    object+object
    ,因为必须在其中一个操作数的类型中声明运算符;
    Point+Point
    必须在
    Point
    中声明;您不能定义
    object+object
    ,因为您没有声明
    object
    ;请注意,所有对象都具有(至少在语言级别)
    =
    /
    !=
    运算符
  • 这里唯一重要的区别是,您不将其称为覆盖(overriding)——不应该错误地认为它们在某种程度上是多态的——它们不是;如果您想将其视为“创建”,这很好,但请记住,在非常重要的情况下,可能会有多个涉及相同类型的重叠运算符,例如使用
    ==
    /
    =运算符,或从非平凡层次结构继承运算符的位置
  • 它是什么;该规范规定,它们必须是
    公共的
    ,因此要么使它们成为
    公共的
    ,要么使用非操作员的
    内部的
    方法
  • 为什么称之为重载

    它被称为“过载”,因为它是过载。当我们为一件事情给出两种可能的实现,然后必须决定使用哪种实现时,我们“重载”了它(这称为重载解析)

    当我们重载方法时,我们使用给定的名称给出一个方法的两个或多个实现。当我们重载运算符时,我们会为一个具有给定语法的运算符提供两个或多个可能的实现。是一样的

    确保没有将重载与重写混淆。重载就是在同一声明空间中存在两个具有相同名称/语法的方法/运算符。重写处理如何在运行时填充虚拟方法槽的内容

    默认情况下,所有对象是否都有所有运算符的实现

    没有

    publicstaticobjectoperator+(objecto1,objecto2)

    没有

    这在某种程度上意味着默认情况下对象没有预定义的操作符,那么术语重载是怎么来的呢

    我不明白这个问题。当然,C#有预定义的运算符

    我不想公开这个操作员

    然后不要使用操作员;创建私有、内部或受保护的方法

    C#的设计是,运算符始终是类型的公共表面积的一部分。如果运算符的含义取决于其使用所在的可访问性域,则会非常混乱。C#被精心设计成一种“质量陷阱”语言,语言设计者的选择使您远离编写混乱、有缺陷、难以重构的程序。要求用户定义的操作符是公共的和静态的是这些微妙的设计要点之一

    (1) 默认情况下,对象没有预定义的运算符

    当然是这样;在各种对象上有数百个预定义操作符。此外,例如,运算符
    +
    有以下预定义的重载:

    int + int
    uint + uint
    long + long
    ulong + ulong
    double + double
    float + float
    decimal + decimal
    enum + underlying  (for any enum type)
    underlying + enum
    int? + int?
    uint? + uint?
    long? + long?
    ulong? + ulong?
    double? + double?
    float? + float?
    decimal? + decimal?
    enum? + underlying?
    underlying? + enum?
    string + string
    object + string
    string + object
    delegate + delegate (for any delegate type)
    
    有关所有其他运算符的所有预定义重载的列表,请参阅C#规范

    请注意,运算符的重载解析有两个阶段:第一,重载解析尝试查找唯一的、最好的用户定义的重载;只有当这样做没有发现适用的候选项时,重载解析才会考虑预定义重载

    (2) 定义运算符并不是说创建运算符,而是说重载(对我来说)与第1点不一致

    我不明白你为什么觉得它不一致,或者,就这一点而言,你觉得什么不一致。术语“过载”一致用于描述操作员和方法;在这两种情况下,它都意味着
    public class Fruit 
    { 
        protected static Shape operator +(Fruit f, Animal a) { ... } 
    }
    
    public class Apple : Fruit
    { 
        ...
        Shape shape = this + giraffe; // Legal!
    }
    public class Giraffe : Animal
    {
        ...
        Shape shape = apple + this; // Illegal!
    }
    
    public class Parent
    {
        public sealed void Foo(int n) { }
    }
    
    public class Child : Parent
    {
        public sealed void Foo(string s) { }
    }
    
    public class Parent
    {
        public virtual int Foo() { return 0; }
    }
    
    public class Child : Parent
    {
        public override int Foo() { return 1; }
    }