Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.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#_.net - Fatal编程技术网

C# 使用接口时访问类上的属性

C# 使用接口时访问类上的属性,c#,.net,C#,.net,我做了这个小控制台应用程序来说明我的问题 我想知道是否有办法访问类的属性,该类是您正在处理的接口的当前实现。在下面的示例中,如果是汽车,我想设置车辆接口属性引擎。当你在做一个新的car实例时,我发现了一种使用括号来实现这一点的方法,但我想稍后通过执行vehicle.Engine=“something”来实现这一点 }即使您的GetVehicle()方法返回一个IVECILE,但这并不意味着它在内部也必须将返回的对象称为IVECILE。它可以明确地将其称为实际(具体)类型,然后可以像往常一样访问其

我做了这个小控制台应用程序来说明我的问题

我想知道是否有办法访问类的属性,该类是您正在处理的接口的当前实现。在下面的示例中,如果是汽车,我想设置车辆接口属性引擎。当你在做一个新的car实例时,我发现了一种使用括号来实现这一点的方法,但我想稍后通过执行vehicle.Engine=“something”来实现这一点


}

即使您的
GetVehicle()
方法返回一个
IVECILE
,但这并不意味着它在内部也必须将返回的对象称为
IVECILE
。它可以明确地将其称为实际(具体)类型,然后可以像往常一样访问其公共属性

因此,您可以简单地执行以下操作:

static IVehicle GetVehicle(VehicleType type)
{
    IVehicle ret = null;

    switch (type)
    {
        case VehicleType.Car:
            var car = new Car() { Name = "Car Name" };
            car.Engine = "V8";
            ret = car;
            break;
        case VehicleType.Bike:
            var bike = new Bike() { Name = "Bike name" }; 
            bike.Mountainbike = true;
            ret = bike;
            break;
    }

    return ret;
}
甚至更短:

static IVehicle GetVehicle(VehicleType type)
{
    switch (type)
    {
        case VehicleType.Car:
            return new Car() { Engine = "V8", Name = "Car Name" };
        case VehicleType.Bike:
            return new Bike() { Mountainbike = true, Name = "Bike name" }; 
    }

    return null;
}

问题是由您启动车辆的位置引起的,您可以从开关返回,因为这是您在该方法中所做的全部操作

switch (type)
{
    case VehicleType.Car:
        return new Car() { Engine = "V8", Name = "Car Name" };
        break;
    case VehicleType.Bike:
        return new Bike() { Mountainbike = true, Name = "Bike name" }; 
        break;
    default:
        break;
}
return null;
你可以这样写:

((Car)vehicle).Engine = "what you want";

只需在需要时铸造对象。

这被称为“泄漏抽象”,不应该这样做:((汽车)车辆)。引擎=“…”。您的代码应该处理合同(接口),而不是具体的实现(类)


在本例中,您应该创建一个扩展IVehicle的ICar接口,并使用它公开Engine属性,并测试IVehicle是否公开ICar。通过这种方式,许多事情可以被视为iHicle,而ICar是一种可以更具体地处理的专门化

IVehicle vehicle= GetVehicle(VehicleType.Car);

// cast car 
Car car = vehicle as Car;

if (car != null)
{
 car.Engine = "V8";
}
基本上,IVehicle没有“引擎”作为属性。这是一种汽车类型的补充。因此,你需要把你的IVehicle放到车上,检查它是否真的是一辆车。如果是,则设置它

如果您认为很多车辆需要发动机,那么您可以:

public interface IVehicleWithEngine :IVehicle
{
 string Engine { get; set; }
}

并让汽车和其他基于“引擎”的车辆实现它。

看看。没错。将接口转换为混凝土类型通常是代码气味的标志。您的答案开始时非常有希望。。。然后,您建议添加另一个接口。这无助于解决OPs问题,也无助于代码中的正确抽象。我认为您的GetVehicle方法目前还可以,因为您正在内部处理具体类,并公开IVehicle。尽管在进一步开发时,您可能需要分为不同的工厂。如果您有一个车辆列表,您可以使用一些linq:vehicles.OfType()。如果您只有一个实例,只需使用'var car=vehicle as ICar',如果不为null,则继续;Bike上的boolean Motorbike属性不是很好。Bike是一个基类,不应该知道任何特定的子类类型。你应该创建一个Motorbike子类,然后删除这个属性。他有一个工厂——在代码中使用特定于类的字段和特性来实际创建特定的类实例是非常好的。如果他使用的是一种接受
iVihicle
的方法,那么你的方法会很好,但他不是这么做的。至于摩托车,它确实说明了类OOP并不是一个很好的抽象。当它被很好地用于正确的问题时,它仍然很强大,但是抽象太容易中断。程序员喜欢树,但有许多问题根本不像树:谢谢你,我现在明白了!:)
public interface IVehicleWithEngine :IVehicle
{
 string Engine { get; set; }
}