c# - 泛型和显式/隐式运算符

标签 c# generics casting operators

考虑以下场景。

我有一个返回 ISomething 的方法, 但它可能是 SomethingWrapped<Something> . 因此,我将结果转换为 Something使用它,但它失败了,任何关于为什么或如何解决它的帮助将不胜感激。

class Program
{
    static void Main(string[] args)
    {
        var a = new DerivedSomething();
        var b = (DerivedSomething)new Wrapped<DerivedSomething>(a); //success
        var c = (DerivedSomething)_GetSomething(false); //success, obsiously!
        var d = (DerivedSomething)_GetSomething(true); //Unable to cast object of type 'test_bed.Wrapped`1[test_bed.DerivedSomething]' to type 'test_bed.DerivedSomething'.
        var e = (DerivedSomething)(ISomething)new Wrapped<DerivedSomething>(a);  //Unable to cast object of type 'test_bed.Wrapped`1[test_bed.DerivedSomething]' to type 'test_bed.DerivedSomething'.

        var works = ((DerivedSomething)_GetSomething(false)).DoSomethingElse(); 
        var fails = ((DerivedSomething)_GetSomething(true)).DoSomethingElse(); //cast exception
    }

    private static ISomething _GetSomething(bool wrap)
    {
        var something = new DerivedSomething();
        return wrap ? new Wrapped<DerivedSomething>(something) : (ISomething)something;
    }
}

public interface ISomething
{
    void DoSomething();
}

public abstract class Something : ISomething
{
    public void DoSomething()
    {
        //some code
    }
}

public class DerivedSomething : Something
{
    public void DoSomething()
    {
        //some code
    }

    public void DoSomethingElse()
    {
        //some code
    }
}

public class Wrapped<T> : ISomething
    where T : ISomething
{
    private readonly T _something;

    public Wrapped(T something)
    {
        _something = something;
    }

    public void DoSomething()
    {
        _something.DoSomething();
    }

    public static explicit operator T(Wrapped<T> wrapped)
    {
        return wrapped._something;
    }
}

似乎如果类型在尝试转换时作为接口(interface)公开,则找不到运算符?

“简单”的解决方案是编写一个“解包”函数,它可以选择解包 Wrapped<Something>Something ,但如果可能的话,我更愿意使用运算符。

编辑

我认为问题的症结在于:_GetSomething()之外我不知道是否SomethingWrapped<Something>将被退回。

最佳答案

显式转换在编译时绑定(bind)(额外提示是转换运算符是静态的)。

尝试

var f = (Something)(Wrapped<Something>)_GetSomething(true);

成功了

在你的例子中,编译器只知道你的类型是 ISomething并且不知道如何转换 ISomethingSomething除非那恰好是 Something已经。

通过改变 public class Wrapped<T> : ISomethingpublic class Wrapped<T> : Something您的示例执行得很好,但是自 Wrapped<T> 以来未调用您的类型转换已经是 T .

注意:
explicit operator不是强制转换,而是类型转换,它是一个调用的方法,该方法是根据编译时类型解析的(在您的情况下为 ISomething )。类型转换与类型转换具有相同的语法,这是一个混淆的根源。转换只是将现有对象分配给兼容类型的不同变量,而类型转换实际上返回一个新对象。

关于c# - 泛型和显式/隐式运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10136543/

相关文章:

c# - 在 C# 中使用典型的 get set 属性...带参数

c# - 为什么 `w("hi")` doesn' t 工作但 `this.w("hi")` 工作?

java - Java 中带有内部节点和迭代器的自定义通用 LinkedList : Type Confusion

c# - 通用索引器重载特化

c# - 使用管理权限启动我的 C# 应用程序

c# - 检查数据库中是否已存在电子邮件地址

java - 在泛型方法的实现中强制类型安全

mysql - SQL 查询连接 4 个表并从 2 个不同的表中获取 2 列的总和

c++ - 指针类型转换

java - 将超出范围的 int 转换为 char。精度损失真的是一个问号吗?