【问题标题】:C# WCF returning parameters with/without REF/OUTC# WCF 返回带/不带 REF/OUT 的参数
【发布时间】:2013-04-18 21:20:57
【问题描述】:

以下是我的 WCF 服务代码的简化版本。这段代码工作正常并返回数据。

我的问题是,这仅在我通过 ref 或 out 传递客户对象时才有效。如果我修改整个代码以便在没有 ref 或 out 的情况下传递客户对象,则 i 变量中的计数为 0。

如果 List 是一个引用变量,为什么它适用于 ref/out 而没有 ref/out 则不起作用。

另外请注意,我将无法从该方法返回一个值,因为我必须返回多个值。

客户代码:

List<Customer> customers = null;
ClientProxy proxy = new ClientProxy();
proxy.GetCustomers(ref customers);
int i = customers.Count;

服务代理:

public class ClientProxy
{
    public void GetCustomers(ref List<Customer> customers)
    {
        INWGetCustomers proxy = new ChannelFactory<INWGetCustomers>("netNamedPipeBinding").CreateChannel();
        proxy.GetCustomers(ref customers);
    }
}

服务合同和数据合同:

[DataContract]
public class Customer
{
    [DataMember]
    public System.String CustomerId;

    [DataMember]
    public System.String CompanyName;
}

[ServiceContract(Namespace = "http://www.temp.com")]
public interface INWGetCustomers
{
    [OperationContract()]
    void GetCustomers(ref List<Customer> customers);
}

服务代码:

public class NWGetCustomersService : INWGetCustomers
{
    public void GetCustomers(ref List<Customer> customers)
    {
        customers = new List<Customer>();
        customers.Add(new Customer() { CustomerId = "1", CompanyName = "A" });
        customers.Add(new Customer() { CustomerId = "2", CompanyName = "B" });
        customers.Add(new Customer() { CustomerId = "3", CompanyName = "C" });
        customers.Add(new Customer() { CustomerId = "4", CompanyName = "D" });
    }
}

【问题讨论】:

    标签: c# wcf out ref


    【解决方案1】:

    我们必须始终牢记,对对象的引用是按值传递的。调用方法时,它将拥有自己的引用值副本。如果参考值在方法内部发生变化,它不会反映在外部变量中。 (我的意思是如果创建了新实例并将相关的引用值分配给方法变量,那么它将不会更新到外部变量)。这就是为什么你必须在你的方法中添加 ref 的原因。执行下面的代码sn-p。然后在方法签名和调用者中添加 ref 关键字修改代码。您可以意识到其中的不同。

    namespace ParameterSample
    {
        class Program
        {
            static void Main(string[] args)
            {
                Customer customer = null;
                GetValue(customer);
                Console.WriteLine("In Main Method : Is customer Null? >>  " + (customer == null));
                Console.Read();
            }
            public static void GetValue(Customer customer)
            {
                customer = new Customer();
                Console.WriteLine("Inside GetValue Method : Is customer Null ? >>  " + (customer == null));
            }
        }
        class Customer
        { }
    }
    

    【讨论】:

    • 您所说的在同一过程中调用方法的情况下是正确的,我确实理解 REF 在这种情况下的作用。当通过 WCF 调用方法时,让我感到困惑的是 REF/OUT 的作用。
    • 目的/概念没有改变,它不是一种力量,它是必须的。#3 行问题说:“如果 List 是一个参考变量,为什么这适用于 ref/out并且没有 ref/out 就无法工作。”重点领域是,了解“引用变量”和“通过引用传递”之间的区别。思想可能导致引用变量是通过引用传递的。这是错误的。它仅按值传递给没有 REF 关键字的任何方法。外部变量和方法变量是堆栈中的不同变量。调用方法时,会将值复制到方法变量中。
    • 1) 您正在传递给方法“customer”变量,并分配了空值。 2)工厂模式是为了创建对象。通用工厂类“ChannelFactory”负责在客户端创建对象。 3)一旦对象被工厂创建,对象的引用值被分配给方法的参数“客户”变量而不是外部变量。 4) 需要了解对象的创建位置。如果我们需要访问在方法内部创建的同一个对象到外部变量,那么我们必须继续使用 REF/OUT。
    • 这个问题没有谈论/与 WCF 相关,即使代码是针对 WCF 的。如果您的疑问得到澄清,请继续享受代码带来的乐趣。
    • 我再次完全同意你所说的。并感谢您对 ChannelFactory 的详尽解释。但我必须重申,我可能没有提到 WCF 这个词,但我的整个代码都与 WCF 有关。所以我的问题也与跨进程传递变量的行为有关。
    【解决方案2】:

    这是因为在这种情况下使用 ref 或 out 会强制将 list 视为输出参数。它不是真正的通过引用传递,因为对象是在服务器和客户端之间发送的。如果您查看 WSDL,您将看到 .NET 是如何生成此代码的

    总结一下:客户端和服务端不是同一个对象,所以list是引用变量没有关系

    【讨论】:

      猜你喜欢
      • 2014-01-12
      • 2011-02-20
      • 1970-01-01
      • 2018-08-15
      • 2019-06-25
      • 1970-01-01
      • 2014-10-24
      • 1970-01-01
      • 2016-07-02
      相关资源
      最近更新 更多