C# 方法能否拒绝Vector2&;的错误类型;矢量3

C# 方法能否拒绝Vector2&;的错误类型;矢量3,c#,unity3d,C#,Unity3d,如果我有一个方法: public void SetPosition(Vector3 position){ // do stuff } 我传递了一个向量2,为什么它仍然允许它并自动转换为(x,y,0) 有没有办法让方法更严格、更错误,而不是自动转换向量?我偶尔会犯这样的错误,但没有意识到这一点,并且会出现一些错误,这些错误需要我花一段时间才能解决 为什么C#甚至允许程序员在传递参数时能够这样做?我不知道是什么库定义了Vector2和Vector3类,但我希望有一个隐式的。此行为已由定义这些

如果我有一个方法:

public void SetPosition(Vector3 position){
   // do stuff
}
我传递了一个向量2,为什么它仍然允许它并自动转换为(x,y,0)

有没有办法让方法更严格、更错误,而不是自动转换向量?我偶尔会犯这样的错误,但没有意识到这一点,并且会出现一些错误,这些错误需要我花一段时间才能解决


为什么C#甚至允许程序员在传递参数时能够这样做?

我不知道是什么库定义了Vector2和Vector3类,但我希望有一个隐式的。此行为已由定义这些类的库实现

一种可能的解决方案是定义第二个位置方法,该方法接受Vector2并抛出:

public void Position(Vector2 position){
  throw new InvalidOperationException();
}

我不知道什么库定义了Vector2和Vector3类,但我希望有一个隐式的。此行为已由定义这些类的库实现

一种可能的解决方案是定义第二个位置方法,该方法接受Vector2并抛出:

public void Position(Vector2 position){
  throw new InvalidOperationException();
}

您无法修复此问题,因为您正在使用的库提供了转换

Unity为
Vector2
定义了一个隐式转换运算符:

Vector2
转换为
Vector3

Vector2
s可以隐式转换为
Vector3
z
在结果中设置为零)

这与您的观察结果一致:对方法
Position
的调用分两步完成-首先,
Vector2
转换为
Vector3
,并将
z
设置为零,然后将结果传递到
Position

有一个技巧可以用来击败转换运算符,但它会降低代码的可读性,因此我建议不要使用它。这个想法基于这样一个事实,即C#不会应用两个隐式转换运算符来满足方法调用,因此您可以这样做:

class Vector3Wrap {
    private readonly Vector3 v;
    private Vector3Wrap(Vector3 v) {
        this.v = v;
    }
    public static implicit operator Vector3Wrap(Vector3 v) {
        return new Vector3Wrap(v);
    }
    public static implicit operator Vector3(Vector3Wrap w) {
        return w.v;
    }
}

public void SetPosition(Vector3Wrap positionWrap){
    Vector3 position = positionWrap;
   // do stuff
}

现在对
SetPosition(myVector3)
的调用将成功,因为
Vector3Wrap
将被隐式创建,但是调用
SetPosition(myVector2)
将失败,因为没有从
Vector2
Vector3Wrap
的隐式转换,您无法修复此问题,因为您正在使用的库提供了一个转换

Unity为
Vector2
定义了一个隐式转换运算符:

Vector2
转换为
Vector3

Vector2
s可以隐式转换为
Vector3
z
在结果中设置为零)

这与您的观察结果一致:对方法
Position
的调用分两步完成-首先,
Vector2
转换为
Vector3
,并将
z
设置为零,然后将结果传递到
Position

有一个技巧可以用来击败转换运算符,但它会降低代码的可读性,因此我建议不要使用它。这个想法基于这样一个事实,即C#不会应用两个隐式转换运算符来满足方法调用,因此您可以这样做:

class Vector3Wrap {
    private readonly Vector3 v;
    private Vector3Wrap(Vector3 v) {
        this.v = v;
    }
    public static implicit operator Vector3Wrap(Vector3 v) {
        return new Vector3Wrap(v);
    }
    public static implicit operator Vector3(Vector3Wrap w) {
        return w.v;
    }
}

public void SetPosition(Vector3Wrap positionWrap){
    Vector3 position = positionWrap;
   // do stuff
}
现在调用
SetPosition(myVector3)
将成功,因为
Vector3Wrap
将被隐式创建,但是调用
SetPosition(myVector2)
将失败,因为没有从
Vector2
Vector3Wrap
的隐式转换

为什么它仍然允许它并自动将其转换为(x,y,0)

原因是Vector2结构的作者编写了一个到Vector3的隐式转换。因为这是Unity3d引擎的一部分,所以您无法真正更改它

有没有办法让方法更严格、更错误,而不是自动转换向量

没有编译器选项可以关闭隐式转换

为什么C#甚至允许程序员在传递参数时能够这样做

它允许类型的作者定义用户不想考虑的“自然”转换。现在,“自然”是一个视角问题。我同意当你认为它们不是自然的时候,它们会变得非常痛苦,所以图书馆的作者必须小心。有。由于Unity3d似乎定义了从Vector3到Vector2的隐式转换,放弃了z分量,因此它们不符合这些要求,这是一个不幸的设计决策。然而,这甚至不是你有问题的转换。无论哪种方式,你都无法摆脱这个库的现状

如果我真的想强制执行不应随意转换为Vector3,我可能会编写某种包装器类型并使用它。一个非常基本的实现是

struct MyVector2
{
    private Vector2 _value;

    public MyVector2(Vector2 v) 
    {
        _value = v;
    }

    public Vector2 Value { get { return _value; } }

    public Vector3 ToVector3()
    {
        return Value;
    }

    public static implicit operator Vector2(MyVector2 v)
    {
        return v.Value;
    }
}
所以这个包装将围绕一个向量2。它允许隐式转换为Vector2,用于任何内置方法,但要传递给Vector3,可以使用ToVector3方法。请注意,该值仍然可以隐式转换,因此请小心使用。同样,这样您就不必在示例中修改设置位置

为什么它仍然允许它并自动将其转换为(x,y,0)

原因是Vector2结构的作者编写了一个到Vector3的隐式转换。因为这是Unity3d引擎的一部分,所以您无法真正更改它

有没有办法让方法更严格、更错误,而不是自动转换向量

没有编译器选项可以关闭隐式转换

为什么C#甚至允许程序员在传递参数时能够这样做

它允许类型的作者定义用户不想考虑的“自然”转换。现在,“自然”是一个视角问题。我同意当你认为它们不是自然的时候,它们会变得非常痛苦,所以图书馆的作者必须小心。有。因为Unity3d似乎定义了隐式转换fr