如何将界面用作" out"参数?

时间:2014-11-14 11:06:51

标签: c# out

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 ”关键字调用函数传递和dog类的实例时,我收到错误:

  

“方法的最佳重载...有一些无效的参数”

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

更新:

test.QueryAnimalProperties(out (IAnimal)my_dog);

尝试输入转换输入也会出错:

  

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

5 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

您不需要输出参数。

但是如果你想使用它,那么使用带有约束的通用方法。

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/

答案 2 :(得分:0)

此处没有理由使用out参数。

从您的方法中删除它,只需更新传递给它的类的属性(在IAnimal界面中可用),如果这是您打算做的。

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

   animal_details.SomeAvailableProperty = "SomeValue";
}

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

答案 3 :(得分:0)

您不会将对象的实例作为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 params视为与函数的返回类型等效,从而更改函数:

public void QueryAnimalProperties(out IAnimal animal_details)

到此:

public IAnimal QueryAnimalProperties()

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

它的工作方式相同。

答案 4 :(得分:0)

这失败了因为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

要解决此问题,请修改DogIAnimal的类型:

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