C# 为什么可以';我不能从对象中访问常数吗?

C# 为什么可以';我不能从对象中访问常数吗?,c#,C#,为什么我不能这样做?这背后有什么原因,还是我试图以错误的方式访问常量 public class Foo { public const int type = 1; } 我知道我可以做Foo.type,但考虑到我的情况,我做不到。例如,如果我有两个从基类继承的类,如下所示: new Foo().type; if(b is Foo){ Console.Write(Foo.type); }elseif.... 我想获取通过printType()函数发送的类的type属性,但我不能

为什么我不能这样做?这背后有什么原因,还是我试图以错误的方式访问常量

public class Foo
{
    public const int type = 1;
}

我知道我可以做
Foo.type
,但考虑到我的情况,我做不到。例如,如果我有两个从基类继承的类,如下所示:

new Foo().type;
if(b is Foo){
    Console.Write(Foo.type);
}elseif....
我想获取通过printType()函数发送的类的
type
属性,但我不能,因为我只能从类访问
type
,而不能访问对象本身

一个解决办法就是

public class Base
{
    ...
}

public class Foo : Base
{
    public const int type = 0;
}

public class Bar : Base
{
    public const int type = 1;
}

public static void printType(Base b)
{
     Console.WriteLine(b.type);
}
但是,如果有许多
Base


解决方案 我最终使用了
readonly
而不是
const
,如下所示:

new Foo().type;
if(b is Foo){
    Console.Write(Foo.type);
}elseif....

是的,您试图以错误的方式访问它。常量与类型的实例不关联-它与类型本身关联。所以你想要:

public readonly int type = 0;
基本上,
const
成员是隐式静态的,而C#不允许您通过值访问静态成员,就好像它们是实例成员一样。(注意,在.NET命名约定中,它应该是
类型
,而不是
类型

编辑:现在您已经解释了实际情况,似乎您正在尝试使用多态性,这对常量不起作用。因此,在基类中应该有一个抽象属性,在子类中实现

int x = Foo.type;
或者,只需在基类中具有一个普通属性,该属性通过基类构造函数填充:

public abstract class Base
{
    public abstract int Type { get; }
}

public class Foo : Base
{
    public override int Type { get { return 0; } }
}

public class Bar : Base
{
    public override int Type { get { return 0; } }
}

如果您只想识别传入对象的动态(最派生的)类型,则可以通过
object.GetType()
方法将其内置到.NET中

public class Base
{
    private readonly int type;
    public int Type { get { return type; } }

    protected Base(int type)
    {
        this.type = type;
    }
}

public class Foo : Base
{
    public Foo() : base(0) {}
}

public class Bar : Base
{
    public Bar() : base(1) {}
}
当然,这与控制附加数据并不完全相同。但是,您可以使用
字典
将任意类型的数据与各种子类相关联。使用子类类型初始值设定项将新条目安装到这样的字典中是合理的

public static void printType(Base b)
{
     Console.WriteLine(b.GetType().Name);
}
公共类基
{
静态内部只读字典类型映射=
新字典();
}
公共类Foo:Base
{
静态Foo{TypeMap.Add(typeof(Foo),0);}
}
公共类栏:基本
{
静态条{TypeMap.Add(typeof(Bar),1);}
}
公共静态void打印类型(基本b)
{
Console.WriteLine(Base.TypeMap[b.GetType()]);
}

这将比每个对象的字段方法慢一点,但是它不会为每个对象添加任何额外的存储。

(另一方面,我认为.NET命名约定不支持创建与
global::System
命名空间的公共成员的命名冲突)@BenVoigt:有很多反例,例如
EventSource.Guid
DebuggerDisplayAttribute.Type
。在大多数情况下,碰撞根本不是问题。。。它只会导致
Foo
类型本身(或子类型)出现问题。在其他地方,您可以参考
Foo.Type
,这并不含糊。@Jon是的,我知道我可以这样做,但考虑到我的场景或我正在尝试做的事情,我不能这样做。请看一下我的例子edit@Krimson:你应该先解释一下。你试图在不适用多态性的地方使用多态性…@JonSkeet:我想这些示例实际上与它们的同名类型相匹配?与类型共享名称的变量(
Color
非常常见)与使用程序员已经有特殊期望的标识符是不同的。注意:不幸的是,这很容易受到复制+粘贴错误的影响(有人在ninja编辑之前捕捉到它们吗?)你的Foo-Foo与酒吧不匹配Bar@demoncodemonkey:谢谢!前两个复制粘贴错误是我自己发现的。你得了3分。我不知道还能有多少。