【问题标题】:Prevent using abstract classes as property type防止使用抽象类作为属性类型
【发布时间】:2017-12-28 08:35:24
【问题描述】:

是否可以防止使用抽象类作为属性类型?

我有一个抽象基类在具有泛型类型的抽象类中继承,而后者又在具有定义类型的类中继承。是否可以用泛型类型“锁定”抽象类,因此不能将其用作其他类的属性?

这是我的情况的近似值。我想防止创建像doubleFoo2 这样的属性的可能性。 Foo<T> 应该只能在其他类中继承,不能直接作为类型使用。

由于我正在验证 PropertyType 的属性及其基本类型,这导致我犯了一个错误,我花了一段时间才找到。这是代码的测试:https://dotnetfiddle.net/OMHmGv

public abstract class FooBase
{
    // Various generic properties and methods
}

public abstract class Foo<T> : FooBase 
{
    public Type ValueType { get { return typeof(T); } }
    public abstract T Value { get; set; }
}

public class DoubleFoo : Foo<double> 
{
    public override double Value { get; set; }
}

public class FooHandler
{
    public DoubleFoo doubleFoo1 { get; set; }
    public Foo<double> doubleFoo2 { get; set; }
}

【问题讨论】:

  • 是否可以用泛型类型“锁定”抽象类,因此不能将其用作其他类的属性? 不,不可能。你为什么关心这样的事情?你想达到什么目的?
  • 您可能需要internalprivate
  • @CodingYoshi 正如我所写:“由于我正在验证属性的 PropertyType 及其基本类型,这导致我犯了一个错误,我花了一段时间才找到。” IE。我想避免再次犯错。
  • 您想要做的事情在 C# 中是不可能的。 Access modifiers 是限制类型曝光的唯一工具。在我看来,你是在浪费时间在这上面。请说明您的目标是什么。
  • 你犯了什么错误?

标签: c# class inheritance abstract


【解决方案1】:

这不仅不可能,而且违背了面向对象编程的三个基本原则之一——当然,我说的是polymorphism
放弃多态就是完全放弃面向对象的编程。

关键是一个类型的引用实际上可以引用从该引用类型派生的任何类型的实例。

多态性使以下代码行完全有效(即使不是很有用):

object s = "the type is actually a string but the reference is of type object";

【讨论】:

  • 谢谢。我只听说过多态性,对它了解不多。是时候阅读它了。 :-)
【解决方案2】:

编辑:就像@Zohar Peled 所说的那样,它违背了多态性的目的,基于命名空间或程序集限制使用是你唯一的方法。

如果 DoubleFoo 及其子类是在单独的程序集中创建的,您可以使用

内部

修饰符而不是

公开

同时用于 FooBase 和 Foo 类,以防止其他程序集访问它们。

如果您必须在同一个程序集中使用这个 DoubleFoo,您可以尝试将基类放在不同的命名空间中以隐藏基实现类。 一个例子是:

FooOfT.cs 内部

namespace FooTester.DoubleFoo.Foo
{
    public abstract class FooBase
    {
        // Various generic properties and methods
    }

    public abstract class Foo<T> : FooBase 
    {
        public Type ValueType { get { return typeof(T); } }
        public abstract T Value { get; set; }
    }
}

在 DoubleFoo.cs 中

using FooTester.DoubleFoo.Foo

namespace FooTester.DoubleFoo
{
    public class DoubleFoo : Foo<double> 
    {
        public override double Value { get; set; }
    }
}

在 FooHandler.cs 中

using FooTester.DoubleFoo

namespace FooTester
{
    public class FooHandler
    {
        public DoubleFoo doubleFoo1 { get; set; }
        // public Foo<double> doubleFoo2 { get; set; } Cannot access Foo<T> class
    }
}

【讨论】:

  • 所有类都在同一个程序集中。但是为基类使用单独的命名空间是个好主意。至少我会收到一条警告,需要添加 using 语句,这将(希望)告诉我我即将做一个 booboo .. :-)
  • 如果您尝试使用来自不同命名空间的类,您会收到警告。如果使用这种方法,您仍然可以在 DoubleFoo 命名空间中创建不同类型的子 Foo 类,并在该命名空间中保持多态性。
猜你喜欢
  • 2010-11-18
  • 2016-02-01
  • 2019-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-01
  • 2017-10-30
相关资源
最近更新 更多