【问题标题】:passing object as a ref parameter to generic method将对象作为 ref 参数传递给泛型方法
【发布时间】:2015-11-22 03:57:38
【问题描述】:

我创建了一个泛型方法,我想通过对该方法的引用传递一个对象来填充几个属性。它编译并运行没有问题,但没有填充对象。

我的通用方法

public static void SplitAddress<T>(ref T ob, string addressToSplit) where T : Address
    {
        //ptr : Postcode, Town, Region
        var ptr = addressToSplit.Split(new char[] { '-' }, 2, StringSplitOptions.RemoveEmptyEntries).ToList();
        var pt = ptr[0].Split(new char[] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries).ToList();

        if (ptr.Count == 2)
        {
            ob.Region = ptr[1];
        }

        for (int x = 0; x < pt.Count; x++)
        {
            switch (x)
            {
                case 0:
                    {
                        ob.PostCode = pt[x];
                        break;
                    }
                case 1:
                    {
                        ob.Town = pt[x];
                        break;
                    }
            }
        }
    }

我想传递的对象

class Merchant : Address
{
    public int MeId { get; set; }
    public int HoId { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
    public string Address { get; set; }
    public string PostCode { get; set; }
    public string Town { get; set; }
    public string Region { get; set; }
    public string VatNr { get; set; }
    public string TRSshopId { get; set; }

}

地址类

abstract class Address
{
    public string PostCode;
    public string Town { get; set; }
    public string Region { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
    public string Adrress { get; set; }
}

方法调用

Methods.SplitAddress<Merchant>(ref me, row.Cells[i].Text);

我可以为两种不同的对象类型创建两个重载方法,但它们会重复相同的代码,这是我想避免的。 它看起来很奇怪,但是例如正在填充“邮政编码”,但是当我将鼠标悬停在“ob”上时,该属性仍然是空的。

【问题讨论】:

  • "我想通过引用这个方法来传递一个对象来填充几个属性"你不需要ref,除非它是struct
  • 你为什么要通过引用传递?您永远不会在方法中为 ob 赋值。鉴于我们不知道数据是什么样子,我们无法说出为什么该方法的行为不像您预期​​的那样,但我认为您应该阅读pobox.com/~skeet/csharp/parameters.html
  • 如果你有T: Address的约束,为什么还要有一个泛型方法?为什么不直接使用Address
  • @MattBurland:虽然它使用ref,但它不适用于Merchant 类型的变量。但是,是的,删除 ref 将允许它仅按值获取 Address 引用...
  • 为什么要在Merchant 类中重新定义Address 中的属性?您的问题可能是由于隐藏了基类中的属性。 Merchant 继承 Address 而不是包含地址似乎很奇怪。

标签: c# object generics pass-by-reference ref


【解决方案1】:

编辑

正如@Lee 敏锐地注意到的那样,您在Member隐藏Address 的属性。由于您的泛型方法仅限于 Address 类型的成员,因此您的代码实际上是在更改隐藏的 Address 类的属性,而不是 Merchant 类的属性,因此如果您没有看到这些更改有一个Merchant 类型的变量。如果您将Member 转换为Address,您将看到这些值。只需从 Merchant 中删除这些属性就可以了。

附言Member inheriting 形式 Address 似乎是错误的 - 成员有一个地址,它不是地址。更好的设计是:

class Merchant
{
    public int MeId { get; set; }
    public int HoId { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }
    public string VatNr { get; set; }
    public string TRSshopId { get; set; }

}

原答案

我想通过对这个方法的引用来传递一个对象来填充一些属性

由于Address 是一个类,您不需要使用ref。引用类型的参数将包含对与传入变量相同的对象的 reference,因此您可以更改该对象的属性值,调用方法将看到更改。 ref 让您做的主要事情是更改对 不同 对象的引用,而您没有这样做,因此使用 ref 不会改变您正在尝试做的事情。

我建议您在调试器中运行它,以确保您的 if 块按照您期望的方式执行。 (例如ptr.Count == 2 是真的吗?它会比2 更大吗?)

您的整个for 块也可以简化为:

if(pt.Count > 0)  ob.PostCode = pt[0];
if(pt.Count > 1)  ob.Town = pt[1];

【讨论】:

  • 你是对的。继承设计是错误的。谢谢。我知道这不是最简单的方法,但我只需要在退出之前了解它。
  • 你的意思是当你有一个地址属性而不是继承?您只需通过属性访问这些字段:merchant.Address.Town。这有多令人不安?
  • 我假设你的意思是Merchant继承Address呢?因为现在Merchant 都继承自Address 并具有Address 属性。
猜你喜欢
  • 2022-01-22
  • 1970-01-01
  • 2013-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多