【问题标题】:Is it possible to access static member variables within a generic method (C#)?是否可以在泛型方法 (C#) 中访问静态成员变量?
【发布时间】:2019-07-31 20:35:32
【问题描述】:

最近我尝试在泛型方法中访问静态列表,但尝试这样做时收到错误。有没有办法在泛型方法中访问静态变量,或者这是不允许的?如果不允许,您介意解释一下原因和可能的解决方法吗?

class Parent
{
    public static List<Parent> staticList = new List<Parent>();
    public Parent()
    {
        staticList.Add(this);
    }

    public static void RemoveItemFromList<T>() where T: Parent, new()
    {
        //This throws an error
        T.staticList.RemoveAt(0);
    }
}

class Child : Parent
{
    public Child()
    {
        staticList.Add(this);
    }
}

当我将鼠标悬停在

T.staticList.RemoveAt(0)

(以红色突出显示)它声明:“'T' 是一个类型参数,在给定的上下文中无效”。

编辑:

很抱歉让您感到困惑。这是修改后的代码sn-p:

我怎样才能让它工作(不使列表非静态,同时保持方法通用):

class Parent
{
    public static List<Parent> staticList = new List<Parent>();

    public static void AGenericMethod<T>() where T: Parent
    {
        Console.WriteLine(T.staticList[0]);
        // This throws an error.
        // 'T' is a type parameter, which is not valid in the given context.
    }
}

class Child : Parent
{
    public static new List<Parent> staticList = new List<Parent>();
}

【问题讨论】:

  • 你为什么不直接做staticList.RemoveAt(0)?静态列表总是在Parent 上定义。如果您需要在孩子中使用不同的列表,那么它不应该是静态的。

标签: c# list oop generics static


【解决方案1】:

我认为您尝试使用 T 在 Parent.staticListChild.staticList 之间进行交换。

据我所知,静态原则上永远不会受到类继承的影响。从来没有静态的Child.staticList。它总是在访问 Parent.StaticList。

我知道只有一种方法可以使静态受到继承的影响——如果静态调用实例函数。我能想到的唯一例子是Equalspublic static bool Equals (object objA, object objB); 在做一些参考相关检查后会调用 objA 的 public virtual bool Equals (object obj);

请注意,您可以定义静态属性。属性主要(但不完全)是 get/set 函数对的语法糖。

【讨论】:

  • 对不起!我真的不清楚我想要达到的目标。我只是提供了代码作为示例,只是放入了一些随机代码和构造函数来填补空白。我真正想知道的是是否可以从泛型方法中访问静态变量。
  • @HenryDenny 当然可以。与所有其他功能相同。所有泛型真正做的是允许您在编译时放入随机类型,帮助您维护类型安全。
  • 是的,这就是我的想法,但是当我尝试使用 T.variableName 形式访问静态变量时,它会引发错误。
  • @HenryDenny 因为 IS 没有 T.variableName。只有变量名。
  • 很抱歉给您带来了困惑。您介意再次阅读我对原始问题所做的编辑吗?谢谢! :)
【解决方案2】:

我不会质疑您的设计。要回答您的问题,您不需要泛型,因为您所做的只是删除索引 0 处的项目。您需要做的就是调用该方法:

public static void RemoveItemFromList() 
{
    staticList.RemoveAt(0);
}

请注意,在您当前的设计中,子元素将被两次添加到静态列表中,因为这两个构造函数都将被调用。如果这不是所需的行为,请删除孩子的 staticList.Add(this); 调用。

即使您想将要删除的对象作为参数传递,使用Parent 类型来传递从它派生的所有对象就足够了,而无需使用约束:

public static void RemoveItemFromList(Parent item)
{
    staticList.Remove(item);
}

//These two would work just fine.
Parent.RemoveItemFromList(parent);
Parent.RemoveItemFromList(child);

更新:

OP 更改了问题,因此解决了第二组注释。

答案还是一样!

这是因为方法是泛型的这一事实并不意味着在后台会生成不同的类。

考虑一下:

public class Sample
{
    public static List<int> staticList = new List<int>();

    public static void AGenericMethod<T>() where T : Sample
    {
        //This works just fine. The static variable is shared by Sample and Sample2
        //Just don't try to qualify it with the generic type.
        staticList.Add(3);
    }
}

public class Sample2 : Sample
{

}

用法:

var sample = new Sample();
var sample2 = new Sample2();

Sample.AGenericMethod<Sample>();
Sample2.AGenericMethod<Sample2>();

这个(内部)结果是一个静态类实例,其中一个变量包含两个类共享的两个3。我相信这就是你想要的。

您可以阅读this interesting explanation了解更多详情。

【讨论】:

  • 对不起!我真的不清楚我想要达到的目标。我只是提供了代码作为示例,只是放入了一些随机代码和构造函数来填补空白。我真正想知道的是是否可以从泛型方法中访问静态变量。
  • @HenryDenny:我已经更新了我的答案。欢迎来到 SO,下次尝试用 actual 问题来引导... :-)
  • @HenryDenny:请花点时间阅读:stackoverflow.com/help/minimal-reproducible-example
  • 对不起,我忘了补充说子类会覆盖(并且必须覆盖)父类的列表。在这种情况下,我必须使用 T.variableName 形式,但它不允许我这样做。
  • 您介意阅读我对原始问题所做的编辑吗?
猜你喜欢
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
  • 2021-11-24
  • 2013-01-22
  • 1970-01-01
  • 2010-11-24
  • 1970-01-01
相关资源
最近更新 更多