我在尝试扩展基类时注意到了一个意外的行为。以下是此问题的示例:
public class Program
{
static void Main(string[] args)
{
var test = new CoolProgram();
test.Start();
}
private void Start()
{
var arr = new object[]
{
1, // int
1L, // long
"Hello World" // string
};
foreach (var dyn in arr.Cast<dynamic>())
{
DoSomething(dyn);
}
Console.ReadKey();
}
protected virtual void DoSomething(int i)
{
Console.WriteLine("Int:" + i);
}
protected virtual void DoSomething(string str)
{
Console.WriteLine("Str:" + str);
}
}
Program
定义了两个由DoSomething
和int
参数重载的方法string
。 Start
方法创建一个对象which contains boxed values. After the definition, the elements will be iterated with casted
dynamic`数组。这到目前为止工作正常(没有长值)。
如果我创建一个额外的继承类CoolProgram
并为long
的类型添加另一个方法,程序将抛出RuntimeBinderException
并告诉我最佳重载是{{1} }。 DoSomething(int)
的方法未执行。
CoolProgram
有人可以解释这种行为或有解决方案吗?
答案 0 :(得分:2)
您的示例可以进一步简化:
static void Main(string[] args)
{
Program test = new CoolProgram();
dynamic i = 1L;
test.DoSomething(i);
//test.Start();
}
问题是,就Start()
方法而言,this
的类型为Program
。为virtual
添加DoSomething()
重载意味着Start()
方法的上下文中没有任何内容。
同样在我上面的简化示例中。编译时类型test
为Program
,就像this
中的Start()
类型为Program
一样。因此,DoSomething(long)
重载在该上下文中不可见,并且无法调用。
如果希望它可见,则需要将其添加到基类,或确保用于调用DoSomething()
的引用静态类型为CoolProgram
。请注意,由于该方法在protected
中声明为CoolProgram
,因此如果您想要将引用的静态类型更改为{{1},那么您还必须更改可访问性。 }。
最后,如果你真的想要完全动态的类型解析,你可以:
CoolProgram
如上所述,上述内容当然需要private void Start()
{
dynamic this2 = this;
var arr = new object[]
{
1, // int
1L, // long
"Hello World" // string
};
foreach (var dyn in arr.Cast<dynamic>())
{
this2.DoSomething(dyn);
}
Console.ReadKey();
}
DoSomething(long)
。
答案 1 :(得分:0)
1)第一个问题是访问修饰符受保护,因为您无法使用Long类型作为参数访问重载方法。我把它改成了内部现在可以访问。
2)第二个问题是你正在创建子类CoolProgram对象但你要调用父类DoSomething方法你应该使用test.DoSomething(dyn);并使子类对象全局化以在Start方法中访问它。
public class Program
{
static CoolProgram test;
static void Main(string[] args)
{
test = new CoolProgram();
test.Start();
}
private void Start()
{
var arr = new object[]
{
1, // int
1L, // long
"Hello World" // string
};
//test.DoSomething(21474836470);
foreach (var dyn in arr.Cast<dynamic>())
{
test.DoSomething(dyn);
}
Console.ReadKey();
}
protected virtual void DoSomething(int i)
{
Console.WriteLine("Int:" + i);
}
protected virtual void DoSomething(string str)
{
Console.WriteLine("Str:" + str);
}
}
// from here child class
public class CoolProgram : Program
{
protected override void DoSomething(int i)
{
// This works
Console.WriteLine("Cool Int: " + i);
base.DoSomething(i);
}
protected override void DoSomething(string str)
{
// This works
Console.WriteLine("Cool Str: " + str);
}
internal virtual void DoSomething(long i)
{
// This is a new method for long
Console.WriteLine("Long Int:" + i);
}
}