【问题标题】:With Type Constraint to a Base Class, the Conversion Operator of the Base Class is Called Even When the Type Parameter is the Sub Class使用基类的类型约束,即使类型参数是子类,也会调用基类的转换运算符
【发布时间】:2012-05-17 21:23:05
【问题描述】:

我正在解决我在解决方案here 中重新创建的问题。

问题是我正在使用一些可以从字符串隐式转换为自身的自定义类型。一种自定义类型继承自另一种。

public class CustomType
{
    public string InnerString { get; protected set; }

    public CustomType(string s)
    {
        InnerString = s;
    }

    #region Operator Overloads
    public static implicit operator CustomType(string s)
    {
        if (s == null)
            throw new ArgumentNullException();
        return new CustomType(s);
    }
    public static implicit operator string(CustomType value)
    {
        if (value == null)
            return null;
        return value.InnerString;
    }
    #endregion
}


public class SubCustomType : CustomType
{
    public SubCustomType(string s)
        : base(s)
    {
        // Nada
    }

    #region Operator Overloads
    public static implicit operator SubCustomType(string s)
    {
        if (s == null)
            throw new ArgumentNullException();
        return new SubCustomType(s);
    }
    public static implicit operator string(SubCustomType value)
    {
        if (value == null)
            return null;
        return value.InnerString;
    }
    #endregion
}

在另一个泛型类中,我依赖于基本自定义类型可以从字符串隐式转换为自身的事实。 (转换发生在(T)this.Rtf 行。.Rtf 是一个字符串。)(在我的例子中,泛型类是 RichTextBox 的一个子类,因为这是我遇到这个问题时使用的。)

public class CustomRichTextBox<T> : Forms.RichTextBox
    where T : CustomType
{
    public object GetValue()
    {
        /// This line throws:
        /// InvalidCastException
        /// Unable to cast object of type 'TestCustomTypesCast.CustomType' to type 'TestCustomTypesCast.SubCustomType'.
        return (T)this.Rtf;
    }
}

public class SubCustomRichTextBox : CustomRichTextBox<SubCustomType>
{
}

当我使用SubCustomRichTextBox(将 SUB 自定义类型作为类型参数的泛型类的一个实例)时,我在GetValue 中转换为T 的那一行收到了一个 InvalidCastException。我认为正在发生的是,为了让编译器能够接受我使用T 从字符串转换的事实,它正在查看CustomType 并看到它的转换过载。但即使我使用CustomType 的子类作为实际类型参数,编译器仍然会使用SubCustomType.CustomType(string s) 来执行转换,而不是使用正确的SubCustomType.SubCustomType(string s) 方法。

谁能指出解决这个问题的方向?我想使用泛型类,因为它允许我重用相同的代码。如果我不能使用泛型,那么我需要在CustomRichTextBox&lt;T&gt; 的几个子类中复制代码。谢谢。

【问题讨论】:

    标签: c# generics operator-overloading


    【解决方案1】:

    这会很困难,因为运算符重载是静态的,而且您实际上是在尝试获得虚拟行为。

    试试这个:

    public class CustomRichTextBox<T> : Forms.RichTextBox
        where T : CustomType, new()
    {
        public object GetValue()
        {
            T t = new T();
            t.InnerString = this.Rtf;
            return t;
        }
    }
    

    请注意,我已将 new() 添加到类型约束中。我还必须将 InnerString 设为可设置。

    顺便说一句,您可以将GetValue() 的返回类型设为T。那可能是一个更好的 API。

    【讨论】:

    • 我希望尽可能地将我的自定义类型表示为值(即不可变)。所以我要做的是创建一个 .SetInnerString 方法,以便在用户调用时更明确它。我试图弄清楚是否有一些使用 dynamic 类型可以解决这个问题(以及这样的解决方案是否更可取!)关于Tobject 的返回类型我同意.这只是我的项目中这个方法实际上是IDataGridViewEditingControl.GetEditingControlFormattedValue这一事实的延续。谢谢你的建议。
    • 为了不变性,如果前一个值为 null(或至少断言失败),您可能希望 .SetInnerString 抛出异常。
    • 这是个好主意。在这种情况下,我可以称它为.InitializeInnerString。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2018-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    • 2019-05-24
    • 1970-01-01
    相关资源
    最近更新 更多