In Scala, I can define structural types as follows:
type Pressable = { def press(): Unit }
This means that I can define a function or method which takes as an argument something that is Pressable, like this:
def foo(i: Pressable) { // etc.
The object which I pass to this function must have defined for it a method called press() that matches the type signature defined in the type - takes no arguments, returns Unit (Scala's version of void).
I can even use the structural type inline:
def foo(i: { def press(): Unit }) { // etc.
It basically allows the programmer to have all the benefits of duck typing while still having the benefit of compile-time type checking.
Does C# have something similar? I've Googled but can't find anything, but I'm not familiar with C# in any depth. If there aren't, are there any plans to add this?
No, and no plans that I know of. Only named (rather than structural) subtyping (e.g. interfaces).
(Others may want to see also
http://en.wikipedia.org/wiki/Nominative_type_system
http://en.wikipedia.org/wiki/Structural_type_system
)
(A few people may point out some exotic corner cases, like the foreach
statement using structural typing for GetEnumerator
, but this is the exception rather than the rule.)
There isn't a way to define structural types that has a particular function. There is a library that adds duck typing support to C# that can be found here.
This is the example from Duck Typing project. Please note the the duck typing happens at runtime and can fail. It is my understanding also that this library generates proxies for the types that are duck typed, which is far cry from the elegant compile-time support that is enjoyed in Scala. This is most likely as good as it gets with this generation of C#.
public interface ICanAdd
{
int Add(int x, int y);
}
// Note that MyAdder does NOT implement ICanAdd,
// but it does define an Add method like the one in ICanAdd:
public class MyAdder
{
public int Add(int x, int y)
{
return x + y;
}
}
public class Program
{
void Main()
{
MyAdder myAdder = new MyAdder();
// Even though ICanAdd is not implemented by MyAdder,
// we can duck cast it because it implements all the members:
ICanAdd adder = DuckTyping.Cast<ICanAdd>(myAdder);
// Now we can call adder as you would any ICanAdd object.
// Transparently, this call is being forwarded to myAdder.
int sum = adder.Add(2, 2);
}
}
This is the C# way of achieving the same thing using the good ol boring interfaces.
interface IPressable {
void Press();
}
class Foo {
void Bar(IPressable pressable) {
pressable.Press();
}
}
class Thingy : IPressable, IPushable, etc {
public void Press() {
}
}
static class Program {
public static void Main() {
pressable = new Thingy();
new Foo().Bar(pressable);
}
}
As others noted, this is not really available in .NET (as this is more a matter of the runtime than a language). However, .NET 4.0 supports similar thing for imported COM interfaces and I believe this could be used for implementing structural typing for .NET. See this blog post:
I didn't try playing with this myself yet, but I think it might enable compiler authors to write languages with structural typing for .NET. (The idea is that you (or a compiler) would define an interface behind the scene, but it would work, because the interfaces would be treated as equivalent thanks to the COM equivalence feature).
Also, C# 4.0 supports the dynamic
keyword which, I think, could be interpreted as a structural typing (with no static type checking). The keyword allows you to call methods on any object without knowning (at compile-time) whether the object will have the required methods. This is essentially the same thing as the "Duck typing" project mentioned by Igor (but that's, of course, not a proper structural typing).
The awaitable pattern in C# can perhaps be interpreted as a limited, ad hoc instance of structural subtyping / existential typing. The compiler will only await
objects that have access to a GetAwaiter()
method that returns any INotifyCompletion
object with a specific set of methods and properties. Since neither the 'awaitable' object nor the 'awaiter' object needs to implement any interface (except INotifyCompletion
in the case of the latter), await
is similar to a method that accepts structurally typed awaitable objects.
来源:https://stackoverflow.com/questions/2831175/does-c-sharp-have-an-equivalent-to-scalas-structural-typing