Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在不强制转换的情况下引用具有不同类型的父变量?_C#_Casting - Fatal编程技术网

C# 如何在不强制转换的情况下引用具有不同类型的父变量?

C# 如何在不强制转换的情况下引用具有不同类型的父变量?,c#,casting,C#,Casting,我有这种情况 public class Base { public Basedef def; } public class A : Base { } public class B : A { public int GetBar() { return def.bar; } } public class BaseDef { } public class ADef : BaseDef { public int foo; } publi

我有这种情况

public class Base
{
    public Basedef def;
}

public class A : Base
{
}

public class B : A
{
    public int GetBar()
    {
        return def.bar;
    }
}


public class BaseDef
{
}

public class ADef : BaseDef
{
    public int foo;
}

public class BDef : ADef
{
    public int bar;
}
如您所见,方法B:GetBar()中有一个错误,因为def无法访问bar,但如果您

public int GetBar()
{
    return (def as BDef).bar;
}
应该可以,但我想避免强制转换,如何使用在基类中创建的引用从定义中获取属性而不使用强制转换

为什么要避免强制转换?因为它容易出现运行时错误,并且更容易引入错误,所以我希望使用类型安全编码

我想做什么

public class Factory
{
    public static Base<BaseDef> Create(BaseDef d)
    {
        if(d is BDef)
            return new B(); //Error, can not convert B to Base<BaseDef>
    }
}

public class Program
{
    B instance = Factory.Create(new BDef()); //Error, can not convert to Base<BaseDef> to B
}
公共类工厂
{
公共静态基创建(BaseDef d)
{
如果(d是BDef)
返回新的B();//错误,无法将B转换为基
}
}
公共课程
{
B instance=Factory.Create(new BDef());//错误,无法将基转换为B
}
我正在寻找一个优雅的解决方案


再见

将Basedef设置为abstract类并将其上的bar设置为抽象属性有意义吗?

将Basedef设置为abstract类并将其上的bar设置为抽象属性有意义吗?

要有一个优雅的、不强制转换的解决方案,编译器需要知道
def
GetBar()中的
BDef
。这是一种实现这一目标的方法,我认为这对您的情况非常有效:

public class Base<T> where T : BaseDef
{
    public T def { get; set; }
}

public class A<T> : Base<T> where T : ADef
{
    public int GetFoo()
    {
        return def.foo; // this works, too
    }
}

public class B : A<BDef>
{
    public int GetBar()
    {
        return def.bar;
    }
}
用法如下:

void Main()
{
    Factory.Create(new BDef());
    Factory.Create<B, BDef>(new BDef());
    Factory.CreateAlternate<B, BDef>(new BDef());
}
void Main()
{
创建(新的BDef());
创建(新的BDef());
CreateAlternate(新的BDef());
}

我喜欢最后一个,因为只要不是问题,就不需要强制转换;如果简明调用代码非常有价值(因为可以推断泛型类型),则喜欢第一个。

要有一个优雅的、不需要强制转换的解决方案,编译器需要知道
def
GetBar()中的
BDef
。这是一种实现这一目标的方法,我认为这对您的情况非常有效:

public class Base<T> where T : BaseDef
{
    public T def { get; set; }
}

public class A<T> : Base<T> where T : ADef
{
    public int GetFoo()
    {
        return def.foo; // this works, too
    }
}

public class B : A<BDef>
{
    public int GetBar()
    {
        return def.bar;
    }
}
用法如下:

void Main()
{
    Factory.Create(new BDef());
    Factory.Create<B, BDef>(new BDef());
    Factory.CreateAlternate<B, BDef>(new BDef());
}
void Main()
{
创建(新的BDef());
创建(新的BDef());
CreateAlternate(新的BDef());
}

我喜欢最后一个,因为只要不存在问题,就没有强制转换,或者如果简明调用代码非常有价值(因为可以推断泛型类型),那么第一个就没有强制转换。

使用强制转换进行转换是不安全的,因为您试图做的基本上不是类型安全的

有一个类a和一个类B是Base的子类,Base有一个对BaseDef的引用。BaseDef可以是ADef或BDef,您不知道是哪一个,当然不能从任何告诉B的信息中得知

但是如果使用泛型,您可以向B提供它需要知道的信息,即它的BaseDef引用实际上是BDef

public class Base<T> where T : BaseDef
{
    public T def;
}

public class A<T> : Base<T> where T : ADef
{
}

public class B : A<BDef>
{
    public int GetBar()
    {
        return def.bar;
    }
}
公共类基类,其中T:BaseDef
{
公共T-def;
}
公共A类:基础,其中T:ADef
{
}
B级:A级
{
公共int GetBar()
{
返回def.bar;
}
}

使用cast执行此操作是不安全的,因为您尝试执行的操作基本上是不安全的

有一个类a和一个类B是Base的子类,Base有一个对BaseDef的引用。BaseDef可以是ADef或BDef,您不知道是哪一个,当然不能从任何告诉B的信息中得知

但是如果使用泛型,您可以向B提供它需要知道的信息,即它的BaseDef引用实际上是BDef

public class Base<T> where T : BaseDef
{
    public T def;
}

public class A<T> : Base<T> where T : ADef
{
}

public class B : A<BDef>
{
    public int GetBar()
    {
        return def.bar;
    }
}
公共类基类,其中T:BaseDef
{
公共T-def;
}
公共A类:基础,其中T:ADef
{
}
B级:A级
{
公共int GetBar()
{
返回def.bar;
}
}
为什么要避免强制转换?因为它容易出现运行时错误,并且更容易引入错误,所以我希望使用类型安全编码

我不明白为什么cast容易出错,如果您不知道
def
RuntimeType
是什么,我会说您的设计是错误的

在我看来,您应该知道它的运行时类型

有一些变通办法

解决方案1:

public int GetBar()
{
    if (def is BDef)
        return ((BDef)def).bar;

    return 0;//some default value
}
解决方案2: 介绍一个
enum
我是谁

public enum DefType
{
    BaseDef = 0,
    ADef =1,
    BDef =2
}

public class BaseDef
{
    public virtual DefType MyType
    {   
        get{ return  DefType.BaseDef; }
    }
}

public class ADef
{
    public override DefType MyType
    {   
        get{ return  DefType.ADef; }
    }
}
然后像这样使用它

switch(def.MyType)
{
    case DefType.ADef:
    {
        (ADef).foo;//you know who is this here right?
    }
    ...
}
为什么要避免强制转换?因为它容易出现运行时错误,并且更容易引入错误,所以我希望使用类型安全编码

我不明白为什么cast容易出错,如果您不知道
def
RuntimeType
是什么,我会说您的设计是错误的

在我看来,您应该知道它的运行时类型

有一些变通办法

解决方案1:

public int GetBar()
{
    if (def is BDef)
        return ((BDef)def).bar;

    return 0;//some default value
}
解决方案2: 介绍一个
enum
我是谁

public enum DefType
{
    BaseDef = 0,
    ADef =1,
    BDef =2
}

public class BaseDef
{
    public virtual DefType MyType
    {   
        get{ return  DefType.BaseDef; }
    }
}

public class ADef
{
    public override DefType MyType
    {   
        get{ return  DefType.ADef; }
    }
}
然后像这样使用它

switch(def.MyType)
{
    case DefType.ADef:
    {
        (ADef).foo;//you know who is this here right?
    }
    ...
}


我假设您希望ADef继承自BaseDef,但您没有编写它,因此将BaseDef强制转换为BDef毫无意义……为什么要避免强制转换?如果没有虚拟方法或属性/reflection,您试图实现的目标是不可能的。我已经编辑了您的问题,假设您的意思是
ADef:BaseDef
。如果不编辑你的问题背面,是的,我的意思是,谢谢你指出sriram,更新的问题,添加了为什么我要避免强制转换我假设你希望ADef继承自BaseDef,但你没有编写它,所以将BaseDef强制转换为BDef没有意义…你为什么要避免强制转换?如果没有虚拟方法或属性/reflection,您试图实现的目标是不可能的。我已经编辑了您的问题,假设您的意思是
ADef:BaseDef
。如果不编辑你的问题背面,是的,我的意思是,感谢你指出sriram,更新的问题,添加了为什么我要避免casting否,因为bar是B的一个特定属性,想法是使用Def类创建a的实例,而Balso,a不应该使用自己的defno访问bar,因为bar是B的一个特定属性,想法是使用Def类创建A的实例,Balso,A不应该使用自己的defI访问bar。考虑到这一点,A可以使用其Def引用获取foo值?@joecabesas是的,我的解决方案支持这一点,因为编译器知道
de