简体   繁体   English

如何使用接口作为“输出”参数?

[英]How can I use an interface as an “out” parameter?

public interface IAnimal
{
}

public interface IDog : IAnimal
{
}

public class Dog : IDog
{
    public bool has_two_legs = false;
}

public static class test
{
    public static void QueryAnimalProperties(out IAnimal animal_details)
    {
        //some sql queries
        animal_details.has_two_legs = true;
    }

    public static void Test()
    {
        Dog my_dog;
        test.QueryAnimalProperties(out my_dog);
    }
}

When I try to call the function passing and instance of the dog class with the " out " keyword I am receiving an error: 当我尝试使用“ out ”关键字调用函数传递和dog类的实例时,收到错误消息:

"The best overload for method ... has some invalid arguments" “方法的最佳重载...具有一些无效的参数”

How am I able to pass a class which implements an interface to my database function to be filled with data? 我如何传递一个实现接口的类到我的数据库函数以填充数据?

UPDATE: 更新:

test.QueryAnimalProperties(out (IAnimal)my_dog);

Trying to type cast the input also gives an error: 尝试类型转换输入也会产生错误:

A ref or out argument must be an assignable variable ref或out参数必须是可分配的变量

QueryAnimalProperties could return an object that is IAnimal , but not IDog (eg ICat ). QueryAnimalProperties可以返回IAnimal而不是IDog的对象(例如ICat )。 Such an object would not be assignable to an IDog variable. 这样的对象将不能分配给IDog变量。 Therefore, this is forbidden. 因此,这是禁止的。

You don't need an out parameter. 您不需要out参数。

But if you want to use it, then use a Generic Method with constraints. 但是,如果要使用它,请使用带有约束的通用方法。

public interface IAnimal
{
    string Name { get; set; }
}

public interface IDog : IAnimal
{

}

public void QueryAnimalProperties<T>(out T animal)
where T : IAnimal, new()
{
    animal = new T();
    animal.Name = "Fred";    
}    

public class Dog : IDog
{
    public string Name { get; set; }
}

void Main()
{
    Dog dog;
    QueryAnimalProperties(out dog);
    Console.WriteLine(dog.Name);
}

Note that if you remove the out parameter without modifying the rest of your code, then your application basically depends on what is known as side-effect, which is something you want to avoid in this situation. 请注意,如果在不修改其余代码的情况下删除out参数,则您的应用程序基本上取决于所谓的副作用,在这种情况下,您需要避免这种情况。

http://codebetter.com/matthewpodwysocki/2008/04/30/side-effecting-functions-are-code-smells/ http://codebetter.com/matthewpodwysocki/2008/04/30/side-effecting-functions-are-code-smells/

There's no reason to use the out parameter here. 这里没有理由使用out参数。

Remove it from your method, and just update the properties of the class you pass to it (that are available in the IAnimal interface), if that's what you're intending to do. 如果您打算这样做,则将其从方法中删除,然后仅更新传递给它的类的属性(可在IAnimal接口中使用)。

public void QueryAnimalProperties(IAnimal animal_details)
{
   //some sql queries

   animal_details.SomeAvailableProperty = "SomeValue";
}

Because the class is already a reference type, when execution returns to whatever method called QueryAnimalProperties , your instance of Dog will retain the values you set in it. 因为该类已经是引用类型,所以当执行返回到称为QueryAnimalProperties任何方法时, Dog的实例将保留在其中设置的值。

You don't pass an instance of an object as an input value for an out parameter, the value will be discarded anyway. 您不会将对象的实例作为out参数的输入值传递,无论如何该值都将被丢弃。

Here's a simple counter-example that demonstrates why it doesn't work: 这是一个简单的反例,演示了为什么它不起作用:

public void QueryAnimalProperties(out IAnimal animal_details)
{
   animal_details = new Hamster();
}

// //

Dog dog;
QueryAnimalProperties(out dog);

In this case, the implementation of QueryAnimalProperties is valid because Hamster : IAnimal and animal_details can accept an object of type Hamster as it implements the interface. 在这种情况下, QueryAnimalProperties的实现是有效的,因为Hamster : IAnimalanimal_details在实现接口时可以接受Hamster类型的对象。

But the caller of QueryAnimalProperties cannot expect animal_details to ultimately resolve as Dog , as my example shows, it might set it to Hamster . 但是QueryAnimalProperties的调用者不能期望animal_details最终像Dog那样解析,如我的示例所示,它可能会将其设置为Hamster

As an aside, I don't think you're using out correctly: out means that the reference itself is changed, as though it were a pointer-to value in C and C++ (or as this is a heap object, it would be pointer-to-pointer value). 顺便说一句,我认为您使用的方式out正确: out表示引用本身已更改,就好像它是C和C ++中的指向指针的值一样(或者因为这是一个堆对象,所以它将是指针到指针的值)。

Consider out params as equivalent to the return-type of the function, change your function from this: 考虑out PARAMS等同于返回类型的功能,你的函数从:

public void QueryAnimalProperties(out IAnimal animal_details)

to this: 对此:

public IAnimal QueryAnimalProperties()

Dog dog = QueryAnimalProperties(); // invalid, QueryAnimalProperties is not guaranteed to return Dog.

and it works the same way. 它以相同的方式工作。

This fails becuase Dog is a concrete class 这是因为Dog是一个具体的类

   public static void Test()
    {
        Dog my_dog; // <-- here
        test.QueryAnimalProperties(out my_dog);
    }

The out variable animal_details in 输出变量animal_details in

public static void QueryAnimalProperties(out IAnimal animal_details)

just promises an IAnimal not necessarily a Dog 只是承诺IAnimal不一定是Dog

To fix this edit the type from Dog to IAnimal : 要解决此问题,请从DogIAnimal修改类型:

   public static void Test()
    {
        IAnimal my_dog; // <-- here
        test.QueryAnimalProperties(out my_dog);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM