可能重复:
如何使用反射调用静态构造函数?
我在各种类的静态构造函数中有一些初始化代码.我不能创建实例,也不提前知道类型.我想确保加载类.
我试过这个:
fooType.TypeInitializer.Invoke (new object[0]);
Run Code Online (Sandbox Code Playgroud)
但得到一个MemberAccessException:类型初始化程序不可调用.
我假设这是因为cctor是私有的?有没有办法在不改变架构的情况下解决这个问题?
编辑:我找到了一个解决方法使用RuntimeHelpers.RunClassConstructor,但这种方式似乎几乎没有在MSDN中记录,我不确定它是一个黑客或一个合理的,prod系统的方式.
我有一个继承TextBoxClass的类,调用它MyTextBox
我想重新定义Background这个类的默认值.
所以我找了一种方法,找到了一个很好的选择:打电话 BackgroundProperty.OverrideMetadata()
麻烦的是:我可以把它放在哪里?
在App.OnStartup()?丑陋而不实用,我希望它在我的Class的代码文件中.
在班级的构造者?我得到一个例外:
PropertyMetadata已经为"MyTextBox"类型注册.
(对我来说似乎很好,我理解为什么我完美地得到这个)
所以我再次看了一下C#中的静态构造函数(之前没有关于那个,遗憾的是)
所以这是我的代码:
public class MyTextBox : TextBox
{
static MyTextBox()
{
MyTextBox.BackgroundProperty.OverrideMetadata(typeof(MyTextBox), new FrameworkPropertyMetadata(App.Current.Resources["CustomBackgroundBrush"]));
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我很高兴这一点,但微软不是.也就是说,当我使用代码分析功能时,我得到这个:
因此我的问题是:我能做些什么呢?
任何提示欢迎,谢谢
编辑:我要补充一点,我不完全理解为什么我会收到此警告,因为我没有在静态构造函数中初始化任何说法,或者是我?
如果我使用 GCC 或 Clang 编译此代码并启用-O2优化,我仍然会得到一些全局对象初始化。任何代码是否有可能访问这些变量?
#include <string>
static const std::string s = "";
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
编译器输出:
main:
xor eax, eax
ret
_GLOBAL__sub_I_main:
mov edx, OFFSET FLAT:__dso_handle
mov esi, OFFSET FLAT:s
mov edi, OFFSET FLAT:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev
mov QWORD PTR s[rip], OFFSET FLAT:s+16
mov QWORD PTR s[rip+8], 0
mov BYTE PTR s[rip+16], 0
jmp __cxa_atexit
Run Code Online (Sandbox Code Playgroud)
具体来说,我没想到这个_GLOBAL__sub_I_main:部分。
编辑:即使使用简单的自定义类型,编译器仍然会生成一些代码。
class Aloha
{
public:
Aloha () : i(1) {}
~Aloha() = default;
private:
int i;
};
static …Run Code Online (Sandbox Code Playgroud) 好的,所以我遇到了以下问题引起了人们的注意.
由于各种原因,我有一个测试设置,其中TestingAssembly.dll中的测试类依赖于BaseTestingAssembly.dll中的TestingBase类.TestBase在此期间所做的一件事就是在自己和调用程序集中查找某个嵌入式资源
所以我的BaseTestingAssembly包含以下几行......
public class TestBase {
private static Assembly _assembly;
private static Assembly _calling_assembly;
static TestBase() {
_assembly = Assembly.GetExecutingAssembly();
_calling_assembly = Assembly.GetCallingAssembly();
}
}
Run Code Online (Sandbox Code Playgroud)
静态,因为我想,这些程序集在应用程序的生命周期内是相同的,所以为什么还要在每次测试时重新计算它们.
在运行时,我注意到_assembly和_calling_assembly分别设置为BaseTestingAssembly而不是BaseTestingAssembly和TestingAssembly.
将变量设置为非静态并将它们初始化为常规构造函数修复此问题,但我很困惑为什么会发生这种情况.我认为静态构造函数在第一次引用静态成员时运行.这可能只来自我的TestingAssembly,那时应该是调用者.有谁知道可能发生了什么?
据我所知,你无法将参数传递给C#中的静态构造函数.但是,在创建类的实例之前,我确实需要传递2个参数并将它们分配给静态字段.我该怎么办呢?
两者有什么不同?我只使用了一种构造函数,我相信它是静态构造函数.只熟悉C++和Java.
我有三个班Base,Derived和Final.Derived源自Base和Final衍生自Derived.这三个类都有一个静态构造函数.类Derived作为公共静态方法调用Setup.当我调用时Final.Setup,我希望所有三个静态构造函数都被执行,但只有一个在Derived运行中.
以下是示例源代码:
abstract class Base
{
static Base()
{
System.Console.WriteLine ("Base");
}
}
abstract class Derived : Base
{
static Derived()
{
System.Console.WriteLine ("Derived");
}
public static void Setup()
{
System.Console.WriteLine ("Setup");
}
}
sealed class Final : Derived
{
static Final()
{
System.Console.WriteLine ("Final");
}
}
Run Code Online (Sandbox Code Playgroud)
这对我来说只是部分有意义.我知道调用Final.Setup()实际上只是一个别名Derived.Setup(),所以跳过静态构造函数Final似乎很公平.但是,为什么不Base调用静态构造函数?
我可以通过调用一个无操作的静态方法Base …
码:
class Base<T,U> where T:Base<T,U>,new() where U :class
{
protected static U _val = null;
internal static void ShowValue()
{
if(_val == null)new T(); //Without this line, it won't work as expected
Console.WriteLine (_val);
}
internal static void Virtual()
{
Console.WriteLine ("Base");
}
}
class Deriv :Base<Deriv,string>
{
static Deriv()
{
_val = "some string value";
}
internal static new void Virtual ()
{
Console.WriteLine ("Deriv");
}
}
public static void Main (string[] args)
{
Deriv.ShowValue();
Deriv.Virtual();
}
Run Code Online (Sandbox Code Playgroud)
由于.NET的泛型,我可以创建一堆特定的类,重用通用基类中定义的泛型静态方法.它可以在一定程度上模仿继承多态性.但是为了初始化不同版本的静态字段,我要使用静态构造函数.不幸的是,我们无法直接调用它们,因此,我们必须找到一种方法来触发它的调用.上面给出的例子显示了一种方法.但我不喜欢实例化或反射方法.我们也不能对泛型参数的静态方法进行约束.所以,我想问一下,如果还有其他办法可以做这种工作!
先谢谢! …
第一次访问静态成员时会执行静态构造函数.知道了这一点,我有几个问题:
[编辑]:我想澄清一点,我不关心微优化.
我问这个问题,因为这是一个设计决定.如果静态构造函数会导致性能损失,那么我将考虑到这一点设计我的代码,并且会更加了解可能影响性能的决策.
这是一个例子来说明我的问题.采用该Independent方法并将其置于单独的静态类中会有什么好处吗?这样,就不必检查静态Test是否已初始化.[ 更新请参阅下面的答案以获得更好,更简单的示例].
static class Test {
// Static constructor with dependent method:
static int x;
static Test() { x = 5; }
static int Dependent() { return x; }
// Static, independent method:
static int Independent(int y) { return y+1; }
}
Run Code Online (Sandbox Code Playgroud)
静态构造函数的执行由应用程序域中发生的以下第一个事件触发:
- 创建了一个类的实例.
- 引用该类的任何静态成员.
我有一些类来缓存数据库中的数据,这些类在调用静态构造函数时会加载数据.
我需要在所有这些类中调用静态Reload方法,除了那些尚未初始化的类.
例如:City缓存数据库中的数据
public class City
{
public City Get(string key)
{
City city;
FCities.TryGetValue(key, out city);
return city;
}
private static Dictionary<string, City> FCities;
static City()
{
LoadAllCitiesFromDatabase();
}
public static void Reload()
{
LoadAllCitiesFromDatabase();
}
private static void LoadAllCitiesFromDatabase()
{
// Reading all citynames from database (a very slow operation)
Dictionary<string, City> loadedCities = new Dictionary<string, City>();
...
FCities = loadedCities;
}
}
Run Code Online (Sandbox Code Playgroud)
问题是City可能尚未使用(它可能不会在此服务中使用),因此没有理由从数据库加载它.
我重新加载所有方法看起来很像这样:
public static class ReloadAll
{
public static void Do()
{
foreach (Type classType …Run Code Online (Sandbox Code Playgroud)