在 C# 中是否可以强制只能从构造函数调用私有函数?
Is it possible in C# to force a private function to be callable from the constructor only?
我发现在某些情况下,构造函数中有很多代码,或者 class 有两个或多个具有可比代码的构造函数。在这些情况下,我通常会创建一个私有方法。前者是为了提高可读性,后者是为了防止重复代码。
在某些情况下,这会导致只能从构造函数调用的私有方法(无论出于何种原因)。有没有办法强制执行此操作?我可以想象做这样的事情:
using System.Diagnostics;
public class Foo
{
private bool _constructing = true;
private Foo()
{
_constructing = false;
}
public Foo(string someString) : this()
{
// constructor-specific code
Initialize();
}
public Foo(double someDouble) : this()
{
// constructor-specific code
Initialize();
}
private void Initialize()
{
Debug.Assert(!_constructing, "Initialize method should only be called from constructor");
// shared code
}
}
但这感觉有些笨拙。谁有更好的建议?
编辑:为示例添加了构造函数链接;我的意思是在原始示例中。
编辑:我想我在原来的问题中遗漏了一点——虽然链接构造函数在某些情况下确实提供了解决方案,但链接的代码总是在您链接的构造函数中的代码之前执行( ,顺便说一句,这就是为什么上面的例子不起作用)。在某些情况下,您想要执行共享代码的某些部分,然后再做其他事情。我将添加另一个示例来反映这一点:
using System.Diagnostics;
public class Foo
{
private bool _constructing = true;
public Foo(string someString)
{
// constructor-specific pre-processing code
Initialize();
// constructor-specific post-processing code
_constructing = false;
}
public Foo(double someDouble)
{
// constructor-specific pre-processing code
Initialize();
// constructor-specific post-processing code
_constructing = false;
}
private void Initialize()
{
Debug.Assert(!_constructing, "Initialize method should only be called from constructor");
// shared code
}
}
您可以为此使用 CallerMemberName
。编译器将用调用该方法的原始方法填充它。在这种情况下 .ctor
(构造函数):
public static class Program
{
static void Main(string[] args)
{
A a = new A();
}
}
class A
{
public A()
{
B();
}
[MethodImplOptions.NoInlining]
private void B([CallerMemberName] string caller = null)
{
if (caller == ".ctor")
{
}
}
}
要防止内联,您可以将 MethodImplOptions.NoInlining
放在方法 B
上。
构造函数可以相互调用:
class Foo
{
private Foo()
{
}
public Foo(int value) : this()
{
}
}
我想,你可以使用这个功能。
我建议你这样做:
public class Foo
{
private Foo()
{
// private constructors can only be called from
// within the class during constuction
}
public Foo(string someString) : this()
{
}
public Foo(double someDouble) : this()
{
}
}
: this()
的使用只能在构造期间调用,虽然这不会强制您的 public 构造函数调用 : this()
,但您没有任何此类保证 public 构造函数无论如何都会调用 Initialize()
。
我发现在某些情况下,构造函数中有很多代码,或者 class 有两个或多个具有可比代码的构造函数。在这些情况下,我通常会创建一个私有方法。前者是为了提高可读性,后者是为了防止重复代码。
在某些情况下,这会导致只能从构造函数调用的私有方法(无论出于何种原因)。有没有办法强制执行此操作?我可以想象做这样的事情:
using System.Diagnostics;
public class Foo
{
private bool _constructing = true;
private Foo()
{
_constructing = false;
}
public Foo(string someString) : this()
{
// constructor-specific code
Initialize();
}
public Foo(double someDouble) : this()
{
// constructor-specific code
Initialize();
}
private void Initialize()
{
Debug.Assert(!_constructing, "Initialize method should only be called from constructor");
// shared code
}
}
但这感觉有些笨拙。谁有更好的建议?
编辑:为示例添加了构造函数链接;我的意思是在原始示例中。
编辑:我想我在原来的问题中遗漏了一点——虽然链接构造函数在某些情况下确实提供了解决方案,但链接的代码总是在您链接的构造函数中的代码之前执行( ,顺便说一句,这就是为什么上面的例子不起作用)。在某些情况下,您想要执行共享代码的某些部分,然后再做其他事情。我将添加另一个示例来反映这一点:
using System.Diagnostics;
public class Foo
{
private bool _constructing = true;
public Foo(string someString)
{
// constructor-specific pre-processing code
Initialize();
// constructor-specific post-processing code
_constructing = false;
}
public Foo(double someDouble)
{
// constructor-specific pre-processing code
Initialize();
// constructor-specific post-processing code
_constructing = false;
}
private void Initialize()
{
Debug.Assert(!_constructing, "Initialize method should only be called from constructor");
// shared code
}
}
您可以为此使用 CallerMemberName
。编译器将用调用该方法的原始方法填充它。在这种情况下 .ctor
(构造函数):
public static class Program
{
static void Main(string[] args)
{
A a = new A();
}
}
class A
{
public A()
{
B();
}
[MethodImplOptions.NoInlining]
private void B([CallerMemberName] string caller = null)
{
if (caller == ".ctor")
{
}
}
}
要防止内联,您可以将 MethodImplOptions.NoInlining
放在方法 B
上。
构造函数可以相互调用:
class Foo
{
private Foo()
{
}
public Foo(int value) : this()
{
}
}
我想,你可以使用这个功能。
我建议你这样做:
public class Foo
{
private Foo()
{
// private constructors can only be called from
// within the class during constuction
}
public Foo(string someString) : this()
{
}
public Foo(double someDouble) : this()
{
}
}
: this()
的使用只能在构造期间调用,虽然这不会强制您的 public 构造函数调用 : this()
,但您没有任何此类保证 public 构造函数无论如何都会调用 Initialize()
。