2012-01-18 43 views
3

这里是我的工作的代码示例:为什么Visual Studio的IntelliSense不适用于派生类?

BaseClass class1; 
    if (userControl.Key == 100) 
    { 
     class1 = new DerivedClass1(); 

     //This does not work, but it seems like it should 
     class1.PropertyInDerivedClass1 = 7 

     //This does work, but why should I have to cast something that I just instantiated? 
     ((DerivedClass1)class1).PropertyInDerivedClass1 = 7; 
    } 
    else 
     class1 = new DerivedClass2(); 

有什么我可以做,以便能够更轻松地访问派生类中的属性和方法?

+0

按照从@DaveShaw保留关键字的响应为C#http://msdn.microsoft.com/en-us/library/x53a06bb.aspx – Lloyd

+3

是的,可以。您可以使用派生类的类型的变量。 – millimoose

+0

您要求的内容需要进行某种数据流分析,以将强制类型转换为编译器可以确定的内容,即分配给变量的当前值,并使语言更加复杂。这听起来像是当语言设计者只需在'if'块中拥有派生类型的局部变量时就不会去的努力。 – millimoose

回答

3

如果您希望使用派生类的变量,则需要使用具有该特定类型的引用来解决它们。

BaseClass obj1; 
DerivedClass dc = new DerivedClass(); 
dc.DerivedPropertyToAccess = value; 
obj1 = dc; 

总之,在您的示例代码错误是访问使用与所述基类类型,而不是派生的类的引用的属性。

2

它不起作用的原因是因为您试图访问DerivedClass1的属性BaseClass,但它们不存在于该类中。仅仅因为存储在变量class1中的对象是包含属性的类型的,并不意味着您可以直接访问这些属性。以这种方式访问​​它们的唯一方法是指定class1DerivedClass1。因此,无论你要投它,或做类似:

BaseClass class1; 
if (userControl.Key == 100) 
{ 
    DerivedClass1 dClass1 = new DerivedClass1(); 

    // This will now work 
    dClass1.PropertyInDerivedClass1 = 7; 

    class1 = dClass1; 
} 
else 
    class1 = new DerivedClass2(); 
1

你可以只使用派生类型的临时变量:

BaseClass baseObj; 
if (…) 
{ 
    var derivedObj = new DerivedClass1(); 
    baseObj = derivedObj; 
    derivedObj.DerivedProperty1 = "foo"; 
} 
else 
{ 
    // Rinse, lather, repeat 
} 

或者,在具体的例子,你可以使用对象初始化剂:

BaseClass baseObj; 
if (…) 
{ 
    baseObj = new DerivedClass1 { 
     DerivedProperty1 = "foo" 
    } 
} // etc… 
2

的C#智能感知使用相同*静态分析,因为编译器

您的代码行:

class1.PropertyInDerivedClass1 = 7 

不给你的智能感知,因为它不工作。这不是有效的C#,因为class1的编译时间类型是BaseClass,并且它没有该属性。

1

自动完成不会使用派生类成员填充,因为class1是BaseClass类型的变量。它不知道你实际上正在创建和分配存储在对BaseClass对象的引用中的派生类型。

我建议创建一个新的本地副本派生类型,将其分配给您的原始类型BaseClass的变量,但使用本地副本,使您的派生唯一函数调用。

BaseClass class1; 
if (userControl.Key == 100) 
{ 
    var derivedObject = new DerivedClass1(); 
    class1 = derivedObject; 

    //This will now work 
    derivedObject.PropertyInDerivedClass1 = 7 
} 
else 
    class1 = new DerivedClass2(); 
12
  1. 选择一个素不相识的人。让他们吃一把剑。
  2. 随机挑选一个剑形吞食者。让他们吃一把剑。

第二个结果是所有的娱乐。在血液,诉讼和最终监禁的第一。

当然,当然,随机的人可能是一个剑吞食者,但如果你不知道他们是那么你不能安全地让他们吃剑。除非通过SwordSwallower引用来处理它们,否则编译器将不会让Person类的实例吃剑。

+1

+1,用最少的代码最有意义。 – Rotem

+0

@Rotem虽然我不清楚初级开发者在当前经济环境下的初级开发者的相对成本。 ;) –

1

考虑这种情况:

// This decides what derived class to return depending on parameters you pass in 
FunkyBase funky = FunkyFactory.Create("A"); 

如果编译器做了一些分析,以确定funky总是FunkyDerivedA的基础上你传递,随后的两段代码是紧密耦合。此代码是说:“我知道这是FunkyBase或从中派生出来的东西,但这就是我所知道的,所以不要给我任何不在该基类上的选项。如果Visual Studio和.NET编译器帮忙,给你所有的方法和属性FunkyDerivedA,那么你可以这样做:

public class FunkyDerivedA : FunkyBase 
{ 
    public SomeProperty { get; set; } 
} 

///// SNIP ///// 

FunkyBase funky = FunkyFactory.Create("A"); 
funky.SomeProperty = 7; 

然后一切正常,因为这是你正在使用的实际对象。但是,然后一个美好的一天有所改变,你想切换到FunkyDerivedB,忘记该属性不存在于该类。

public class FunkyDerivedA : FunkyBase 
{ 
    public SomeProperty { get; set; } 
} 

// notice it doesn't have the same property 
public class FunkyDerivedB : FunkyBase 
{ 
} 

///// SNIP ///// 

// Danger, Will Robinson! 
FunkyBase funky = FunkyFactory.Create("B"); 
funky.SomeProperty = 7; 

在这一点上,事情可能会以非常不明显的方式失败。投射是你的信号,你知道你在做什么。这是对您或任何维护您的代码的人的提醒,即您正在对您获得的对象的类型(在本例中为工厂方法)做出假设,并且在更改此代码时应小心谨慎。

现在,这并不意味着C#不能做你在问什么。它可以在一定程度上。

从.NET 3.0中,var关键字(见the MSDN article)让你放弃声明类型:

var funky = new FunkyDerivedA(); 

智能感知和编译时类型检查的工作,它只是计算出的类型是什么基于方法的返回类型。请注意,在我上面的工厂示例中,如果Create方法刚刚返回基类,那么这将是该类型。它不会根据对调用树的分析或类似的东西将它转换为更派生的类。

从.NET v4.0开始,您可以使用dynamic(请参阅the MSDN article)关键字,该关键字放弃编译时类型检查,以便让您按照自己的意愿进行操作。当然,如果你弄错了,你会得到一个运行时异常(不是编译时错误),因为它在运行时解决,而不是编译时。同样,Intellisense也不起作用,所以要确保您知道对象是什么以及可用的成员。

另请注意,与铸造一样,dynamic关键字也是一个信号,表示您知道自己在做什么,并对任何不正确的事情承担责任。

希望帮助

相关问题