如何在 C# 中使用 T 类型进行类型转换并访问其 属性 和变量

How to typecast in c# with T type and access its property and variables

IDE:C#.net,Winforms

在我开始之前请看一下情况:

 public class ParentClass
{

}


public class A : ParentClass
{
    public int A_item1;
    public string A_item2;
    public int CommonVariable;
}

public class B : ParentClass
{
    public int B_item1;
    public string B_item2;
    public int CommonVariable;
}  

现在我有 form1.cs 从我使用它的地方

  private void button1_Click(object sender, EventArgs e)
    {
        List<ParentClass> lstA = new List<ParentClass>();
        lstA.Add(new A());
        lstA.Add(new A());

        List<ParentClass> lstB = new List<ParentClass>();
        lstA.Add(new B());
        lstA.Add(new B());

        lstA = AssignValue<A>(lstA);

        lstB = AssignValue<B>(lstB);



    }

    private List<ParentClass> AssignValue<T>(List<ParentClass> lstParent)
    {
        foreach (var item in lstParent)
        {
            (item as T).CommonProperty = 5;  // can you tell me how to dynamically type cast here, what ever type is supplied it will type cast accordingly..
        }
        return lstParent;

    }

如您所见,我创建了 2 个子 classes A、B 和一个 ParentClass,

在 form1.cs 中,我创建了 2 个类型为 Parentclass 的列表,并在列表 1 中添加类型对象,在列表 2 中添加 B 类型对象,并将其传递给函数 AssignValues

在这里我想自动键入种姓,无论用户提供类型 T,你能告诉我如何实现这一点。

请不要建议我在父类中移动这个变量,因为在我的项目中我不能修改父类class,我也不想用switch case来解决这个问题。

我还是很困惑,但是我在例子中得到的,你可以像这样使用动态(C#4.0)-

private List<ParentClass> AssignValue<T>(List<ParentClass> lstParent)
    {
        foreach (var item in lstParent)
        {
            dynamic objData = Convert.ChangeType(item, typeof(T));
            if (objData != null)
            {
                //This call would throw exception if CommonProperty is not member of the T Class
                objData.CommonProperty = 5;
            }
        }
        return lstParent;

    }

如果这不是您想要的情况,请详细说明您面临的问题是什么

创建新界面:

public interface IHasCommonProperty
{
    int CommonProperty {get; set;}
}

public class A : ParentClass, IHasCommonProperty
{
    public int A_item1;
    public string A_item2;
    public int CommonProperty {get ; set; }
}

public class B : ParentClass, IHasCommonProperty
{
    public int B_item1;
    public string B_item2;
    public int CommonProperty {get ; set; }
}  

private List<ParentClass> AssignValue(List<ParentClass> lstParent)
{
    foreach (var item in lstParent)
    {
        var commonInterface = item as IHasCommonProperty;
        if (commonInterface != null)
            commonInterface.CommonProperty = 5;
    }
    return lstParent;
}

您需要做的是让编译器知道您的 classes 是如何布局的。

基本上你必须告诉它,"this T type, here's what I know about it"。

由于两者之间没有任何共同点,除了两个属性具有相同的名称和类型之外,编译器不会让您轻易地做到这一点。请注意,具有相同名称和类型但属于不同类型的两个属性是不同的属性,您可以将其强制转换为允许您访问它们的通用属性。

除了 dynamic 之外,这里已经有另一个答案,但让我们找到一个更好的方法。

你要做的就是将公共 属性 向下移动到你的公共基础 class:

public class ParentClass
{
    public int CommonVariable;
}


public class A : ParentClass
{
    public int A_item1;
    public string A_item2;
}

public class B : ParentClass
{
    public int B_item1;
    public string B_item2;
}  

然后你必须告诉泛型方法,它将作为 T 给出的所有类型至少是公共基础 class:

private List<ParentClass> AssignValue<T>(List<ParentClass> lstParent)
    where T : ParentClass

看到我上面加的那个where T : ParentClass子句,这告诉编译器每个类型都是那个类型,现在代码可以这样写:

{
    foreach (var item in lstParent)
        item.CommonVariable = 5;
    return lstParent;
}

现在,说了这么多我质疑这个方法的有效性。

就目前而言,您实际上不需要它是通用的。如果将公共域下移到基class,你可以这样写方法:

private List<ParentClass> AssignValue(List<ParentClass> lstParent)
{
    foreach (var item in lstParent)
        item.CommonVariable = 5;
    return lstParent;
}

如果您不能或不愿将公共字段向下移动到基中class,您可以使用另一种方式,使用接口。

首先将字段变成 属性,然后声明一个接口公开此 属性 并在每个 class 上实现 属性,然后让方法,仍然不必是通用的,采用该接口:

public class ParentClass
{
}

public interface ICommon
{
    int CommonVariable { get; set; }
}

public class A : ParentClass : ICommon
{
    public int A_item1;
    public string A_item2;
    public int CommonVariable { get; set; }
}

public class B : ParentClass : ICommon
{
    public int B_item1;
    public string B_item2;
    public int CommonVariable { get; set; }
}  

private List<ICommon> AssignValue(List<ICommon> lstParent)
{
    foreach (var item in lstParent)
        item.CommonVariable = 5;
    return lstParent;
}