如何将接口用作“out”参数

本文关键字:out 参数 接口 | 更新日期: 2023-09-27 18:30:18

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);
    }
}

当我尝试使用"out"关键字调用函数传递和狗类的实例时,我收到错误:

"方法的最佳过载...有一些无效的参数"

我如何能够将实现接口的类传递给我的数据库函数以填充数据?

更新:

test.QueryAnimalProperties(out (IAnimal)my_dog);

尝试类型转换输入也会给出错误:

引用或 out 参数必须是可赋值变量

如何将接口用作“out”参数

QueryAnimalProperties可以返回一个IAnimal的对象,但不能返回IDog的对象(例如 ICat )。此类对象不可分配给IDog变量。因此,这是禁止的。

你不需要 out 参数。

但是,如果要使用它,请使用具有约束的泛型方法。

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);
}

请注意,如果在不修改其余代码的情况下删除 out 参数,则应用程序基本上取决于所谓的副作用,在这种情况下您希望避免这种情况。

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

没有理由在这里使用 out 参数。

从方法中删除它,只需更新传递给它的类的属性(在IAnimal接口中可用),如果这是您要执行的操作。

public void QueryAnimalProperties(IAnimal animal_details)
{
   //some sql queries
   animal_details.SomeAvailableProperty = "SomeValue";
}

由于该类已经是引用类型,因此当执行返回到名为 QueryAnimalProperties 的任何方法时,Dog 的实例将保留您在其中设置的值。

您不会将对象的实例作为out参数的输入值传递,该值无论如何都会被丢弃。

这里有一个简单的反例,说明了为什么它不起作用:

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

//

Dog dog;
QueryAnimalProperties(out dog);

在这种情况下,QueryAnimalProperties 的实现是有效的,因为 Hamster : IAnimalanimal_details 可以在实现接口时接受类型 Hamster 的对象。

但是QueryAnimalProperties的调用方不能期望animal_details最终解析为Dog,如我的示例所示,它可能会将其设置为 Hamster

顺便说一句,我认为您没有正确使用outout意味着引用本身已更改,就好像它是 C 和 C++ 中的指针值(或者由于这是一个堆对象,它将是指针到指针值)。

out参数视为等效于函数的返回类型,从中更改函数:

public void QueryAnimalProperties(out IAnimal animal_details)

对此:

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

它的工作方式相同。

这失败了,因为Dog是一个具体的类

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

输出变量animal_details

public static void QueryAnimalProperties(out IAnimal animal_details)

只是承诺一个IAnimal不一定是Dog

要解决此问题,请将类型从Dog编辑为IAnimal

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