【问题标题】:Can an interface require a property, but not specify a required type?接口可以需要一个属性,但不指定所需的类型吗?
【发布时间】:2012-04-12 01:56:24
【问题描述】:

我有一个简单的接口,定义如下:

interface iFace
{
   int Value { get; }
}

在这种情况下,任何实现 iFace 的类都必须有一个名为 Value 的 int 类型的属性。这个接口的使用将与数据绑定一起使用,我不在乎属性是什么类型。我有什么选择吗?我想避免这种解决方案:

interface iFace<T>
{
   T Value { get; }
}

因为我想引用接口而不指定类型

编辑:

我希望能够将相同的界面应用到 NumericUpDown 控件和 Trackbar 控件。一个value属性是decimal类型,另一个是int类型。

在这种情况下,将属性设为 object 类型是行不通的。

【问题讨论】:

  • 这就是 dynamic 关键字的设计目的。
  • 我对 .net 3.5 和更新版本比较陌生,我将不得不研究动态。
  • @HansPassant 值得一提的是,一个dynamic属性实际上会被类型化为一个object,所以在使用接口时它会显示为这样在另一种语言中 - 并且大概是在 C# 项目中用作程序集引用时。我不知道如果跨项目使用它作为 VS 解决方案中的项目参考会发生什么;我好奇。如果我记得这样做,我会在上班时检查一下。
  • 是不是写界面太费时间了?你不能为 int/double 类型编写另一个接口......如果你不想要通用接口?通用接口是解决这个问题的方法。

标签: c# .net generics types interface


【解决方案1】:

如果不关心是否是严格类型的,将属性类型改为对象。

【讨论】:

    【解决方案2】:

    试试这个:

    interface MyInterface
    {
        Object MyProperty
        {
            get;
            set;
        }
    }
    
    class MyClass : MyInterface
    {
        Object MyInterface.MyProperty
        {
            get
            {
                return this.MyProperty;
            }
            set
            {
                if (value is MyType)
                    this.MyProperty = (MyType)value;
            }
        }
    
        public MyType MyProperty
        {
            get;
            set;
        }
    }
    

    【讨论】:

    • 我认为这将是最好的答案。我正在将此界面应用于超过 15 个控件,并且我试图避免为所有控件添加显式界面。
    【解决方案3】:

    响应您的编辑:您遇到了众所周知的问题,即 .NET 没有 INumeric 接口。它存在于我见过的源代码中,但已被注释掉,这表明微软已经足够重视它并遇到了一些重大问题。

    Danny Varod 的解决方案很好;您还可以通过创建通用和接口的非通用版本来扩展它。另一种解决方案是向接口添加表示您现在使用数学运算符的数字运算的方法,例如Increment()。

    这里我将调用接口IHasValue(部分是因为它有点喜剧):

    interface IHasValue
    {
        object Value { get; set; }
        void Increment();
        void Decrement();
    }
    
    interface IHasValue<TValue> : IHasValue { new TValue Value { get; set; } }
    
    abstract class UpDownValueControl<T> : IHasValue<T>
    {
        public T Value { get; set; }
        object IHasValue.Value
        {
             get { return this.Value; }
             set { this.Value = (T)value; }
        }
        public abstract void Increment();
        public abstract void Decrement();
    }
    class NumericUpDownControl : UpDownValueControl<decimal>
    {
        public override void Increment() { Value++; }
        public override void Decrement() { Value--; }
        //rest of the implementation
    }
    class TrackbarControl : UpDownValueControl<int>
    {
        public override void Increment() { Value++; }
        public override void Decrement() { Value--; }
        //rest of the implementation
    }
    

    令人沮丧的是,基类不能处理像增量和减量方法这样的重复代码,但至少这种方法允许基类处理除重复之外的所有其他代码数学运算符代码。

    最后,我怀疑这种解决方案的复杂性增加的成本大于收益;我认为我更有可能采用 Danny Varod 的解决方案。

    【讨论】:

      猜你喜欢
      • 2011-09-08
      • 1970-01-01
      • 1970-01-01
      • 2022-12-08
      • 2021-10-29
      • 2021-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多