After looking at how Go handles interfaces and liking it, I started thinking about how you could achieve similar duck-typing in C# like this:
var mallard = new Mallard(); // doesn't implement IDuck but has the right methods
IDuck duck = DuckTyper.Adapt<Mallard,IDuck>(mallard);
The DuckTyper.Adapt method would use System.Reflection.Emit to build an adapter on the fly. Maybe somebody has already written something like this. I guess it's not too different from what mocking frameworks already do.
However, this would throw exceptions at run-time if Mallard doesn't actually have the right IDuck methods. To get the error earlier at compile time, I'd have to write a MallardToDuckAdapter which is exactly what I'm trying to avoid.
Is there a better way?
edit: apparently the proper term for what I call "safe duck-typing" is structural typing.
How can you know if a cow walks like a duck and quacks like a duck if you don't have a living, breathing cow in front of you?
Duck-typing is a concept used at run-time. A similar concept at compile-time is structural typing which is AFAIK not supported by the CLR. (The CLR is centred around nominative typing.)
[A structural type system] contrasts with nominative systems, where comparisons are based on explicit declarations or the names of the types, and duck typing, in which only the part of the structure accessed at runtime is checked for compatibility.
The usual way to ensure that duck-typing throws no exception at run-time are unit-tests.
DuckTyping for C#
Reflection.Emit is used to emit IL that directly calls the original object
I don't think this library will give you compile time errors thought, I am not sure that would be entirely feasible. Use Unit Tests to help compensate for that.
I don't think there's another way in which you would get a compile time error.
However, this is something that Unit Testing is great for. You would write a unit test to verify that
DuckTyper.Adapt<Mallard, IDuck>(mallard);
successfully maps.
I know that implicit interfaces (which is what Go interfaces are) were planned for VB 10 (no idea about C#). Unfortunately, they were scrapped before release (I think they didn’t even make it into beta …). It would be nice to see whether they will make an appearance in a future version of .NET.
Of course, the new dynamic types can be used to achieve much the same but this is still not the same – implicit interfaces still allow strong typing, which I find important.
Related
It is common to read around that object casting is a bad practice and should be avoided, for instance Why should casting be avoided? question has gotten some answers with great arguments:
By Jerry Coffin:
Looking at things more generally, the situation's pretty simple (at
least IMO): a cast (obviously enough) means you're converting
something from one type to another. When/if you do that, it raises the
question "Why?" If you really want something to be a particular type,
why didn't you define it to be that type to start with? That's not to
say there's never a reason to do such a conversion, but anytime it
happens, it should prompt the question of whether you could re-design
the code so the correct type was used throughout.
By Eric Lippert:
Both kinds of casts are red flags. The first kind of cast
raises the question "why exactly is it that the developer knows
something that the compiler doesn't?" If you are in that situation
then the better thing to do is usually to change the program so that
the compiler does have a handle on reality. Then you don't need the
cast; the analysis is done at compile time.
The second kind of cast raises the question "why isn't the operation
being done in the target data type in the first place?" If you need
a result in ints then why are you holding a double in the first
place? Shouldn't you be holding an int?
Moving on to my question, recently I have started to look into the source code of the well known open source project AutoFixture originally devloped by Mark Seemann which I really appreciate.
One of the main components of the library is the interface ISpecimenBuilder which define an somehow abstract method:
object Create(object request, ISpecimenContext context);
As you can see request parameter type is object and by such it accepts completely different types, different implementations of the interface treat different requests by their runtime type, checking if it is something they cable dealing with otherwise returning some kind of no response representation.
It seems that the design of the interface does not adhere to the "good practice" that object casting should be used sparsely.
I was thinking to myself if there is a better way to design this contract in a way that defeats all the casting but couldn't find any solution.
Obviously the object parameter could be replaced with some marker interface but it will not save us the casting problem, I have also thought that it is possible to use some variation of visitor pattern as described here but it does not seem to be very scalable, the visitor will must have dozens of different methods since there is so many different implementations of the interface that capable dealing with different types of requests.
Although the fact that I basically agree with the arguments against using casting as part of a good design in this specific scenario it seems as not only the best option but also the only realistic one.
To sum up, is object casting and a very general contracts are inevitability of reality when there is a need to design modular and extendable architecture?
I don't think that I can answer this question generally, for any type of application or framework, but I can offer an answer that specifically talks about AutoFixture, as well as offer some speculation about other usage scenarios.
If I had to write AutoFixture from scratch today, there's certainly things I'd do differently. Particularly, I wouldn't design the day-to-day API around something like ISpecimenBuilder. Rather, I'd design the data manipulation API around the concept of functors and monads, as outlined here.
This design is based entirely on generics, but it does require statically typed building blocks (also described in the article) known at compile time.
This is closely related to how something like QuickCheck works. When you write QuickCheck-based tests, you must supply generators for all of your own custom types. Haskell doesn't support run-time casting of values, but instead relies exclusively on generics and some compile-time automation. Granted, Haskell's generics are more powerful than C#'s, so you can't necessarily transfer the knowledge gained from Haskell to C#. It does suggest, however, that it's possible to write code entirely without relying on run-time casting.
AutoFixture does, however, support user-defined types without the need for the user to write custom generators. It does this via .NET Reflection. In .NET, the Reflection API is untyped; all the methods for generating objects and invoking members take object as input and return object as output.
Any application, library, or framework based on Reflection will have to perform some run-time casting. I don't see how to get around that.
Would it be possible to write data generators without Reflection? I haven't tried the following, but perhaps one could adopt a strategy where one would write 'the code' for a data generator directly in IL and use Reflection emit to dynamically compile an in-memory assembly that contains the generators.
This is a bit like how the Hiro container works, IIRC. I suppose that one could design other types of general-purpose frameworks around this concept, but I rarely see it done in .NET.
Why are the container classes in System.Collections.Immutable, ie ImmutableList<T> sealed ?
I would like to inherit them and have to go through an ugly and error prone composition+proxy ..
Just trying to understand the reason here ?
All types should be sealed unless they are specifically and carefully designed for extension. Designing for extension is difficult and expensive and easy to do wrong.
Moreover: there are security and correctness implications when you use a type that allows extension. By making the type sealed, the authors of the type are telling the consumers of that type "if you receive an instance of this type, you can rely on the fact that you are actually getting the type that was written by Microsoft, tested by Microsoft, and had the source code published by Microsoft". You can write tests and have confidence that the runtime behaviour will match the test time behaviour because no one else is capable of making their own crazy extension that has a bug.
The question is backwards. You should never ask for a reason for a type to be sealed; sealed should have been the default in the language. Rather, we need a reason to unseal a type: because it was designed for extension, because it was implemented by professionals who carefully understood all the implications of extension, and because consumers of the type were willing to take on the risks of not knowing what the code they're calling actually does.
I realize that it goes against the strongly typed nature of C#, but I find that when working with dynamic objects in the language, some of the more useful features typically found in JavaScript or PowerShell are simply not practical.
For example, the following C# code will fail at runtime and it's obvious why.
dynamic x = 1.0;
int y = x;
But that makes the dynamic features of C# pretty limited when dealing with loosely typed data such as that produced by JSON payloads or CSV where subtle variations in the representation can result in very different behavior at runtime.
What I'm looking for is something that will behave much like the VBA / VBScript era Variant type. I imagine it's possible to derive such a type from DynamicObject that would wrap primitive values like Int32, String, etc and perform the appropriate casts at runtime. I've done something similar with "null" values in dynamic contexts.
But is there anything like this already established? I've looked around GitHub or Codeplex to no avail but it's kind of a hard thing to search for. Before I get started on what I imagine is going to be quite a complicated class, I want to make sure I'm not wasting my time.
About the practicality of all of this
I should note that I resisted the concept of dynamic dispatch in C# for a long time because it was not intended to be a dynamic language. Quite honestly, I wish it wasn't added to the language at all, or at least restricted to COM interop scenarios.
But having said that, I am always curious about ways to "hack" language features in such a way to make them do things that they were never intended to do. Sometimes something useful comes out of it. For example, there have been plenty of examples of people using the IDisposable interface and using statement to do things that have nothing to do with releasing resources.
I doubt I would use this in production applications or anything that needed to be handed off to another developer.
The visual basic languages hide a lot of the glue, that just isn't the C# way. The Variant type has a raft of conversion functions, they are invoked automatically by the vb runtime. .NET has automatic conversion functions too, you just have to use them explicitly:
dynamic x = 1.0;
int y = Convert.Int32(x);
With the C# justification for having to write code like that because it is not a language that hides cost.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
For c# developers that are staring out to learn Java, are there any big underlying differences between the two languages that should be pointed out?
Maybe some people may assume things to be the same, but there are some import aspects that shouldn't be overlooked? (or you can really screw up!)
Maybe in terms of OOP constructs, the way GC works, references, deployment related, etc.
A few gotchas off the top of my head:
Java doesn't have custom value types (structs) so don't bother looking for them
Java enums are very different to the "named numbers" approach of C#; they're more OO. They can be used to great effect, if you're careful.
byte is signed in Java (unfortunately)
In C#, instance variable initializers run before the base class constructor does; in Java they run after it does (i.e. just before the constructor body in "this" class)
In C# methods are sealed by default. In Java they're virtual by default.
The default access modifier in C# is always "the most restrictive access available in the current context"; in Java it's "package" access. (It's worth reading up on the particular access modifiers in Java.)
Nested types in Java and C# work somewhat differently; in particular they have different access restrictions, and unless you declare the nested type to be static it will have an implicit reference to an instance of the containing class.
here is a very comprehensive comparison of the 2 languages:
http://www.25hoursaday.com/CsharpVsJava.html
Added: http://en.wikipedia.org/wiki/Comparison_of_Java_and_C_Sharp
I am surprised that no one has mentioned properties, something quite fundamental in C# but absent in Java. C# 3 and above has automatically implemented properties as well. In Java you have to use GetX/SetX type methods.
Another obvious difference is LINQ and lambda expressions in C# 3 absent in Java.
There are a few other simple but useful things missing from Java like verbatim strings (#""), operator overloading, iterators using yield and pre processor are missing in Java as well.
One of my personal favourites in C# is that namespace names don't have to follow the physical directory structure. I really like this flexibility.
There are a lot of differences, but these come to mind for me:
Lack of operator overloading in Java. Watch your instance.Equals(instance2) versus instance == instance2 (especially w/strings).
Get used to interfaces NOT being prefixed with an I. Often you see namespaces or classes suffixed with Impl instead.
Double checked locking doesn't work because of the Java memory model.
You can import static methods without prefixing them with the class name, which is very useful in certain cases (DSLs).
Switch statements in Java don't require a default, and you can't use strings as case labels (IIRC).
Java generics will anger you. Java generics don't exist at runtime (at least in 1.5), they're a compiler trick, which causes problems if you want to do reflection on the generic types.
.NET has reified generics; Java has erased generics.
The difference is this: if you have an ArrayList<String> object, in .NET, you can tell (at runtime) that the object has type ArrayList<String>, whereas in Java, at runtime, the object is of type ArrayList; the String part is lost. If you put in non-String objects into the ArrayList, the system can't enforce that, and you'll only know about it after you try to extract the item out, and the cast fails.
One thing I miss in C# from Java is the forced handling of checked exceptions. In C# is it far to common that one is unaware of the exceptions a method may throw and you're at the mercy of the documentation or testing to discover them. Not so in Java with checked exceptions.
Java has autoboxing for primitives rather than value types, so although System.Int32[] is an array of values in C#, Integer[] is an array of references to Integer objects, and as such not suitable for higher performance calculations.
No delegates or events - you have to use interfaces. Fortunately, you can create classes and interface implementations inline, so this isn't such a big deal
The built-in date/calendar functionality in Java is horrible compared to System.DateTime. There is a lot of info about this here: What's wrong with Java Date & Time API?
Some of these can be gotchas for a C# developer:
The Java Date class is mutable which can make returning and passing dates around dangerous.
Most of the java.util.Date constructors are deprecated. Simply instantiating a date is pretty verbose.
I have never gotten the java.util.Date class to interoperate well with web services. In most cases the dates on either side were wildly transformed into some other date & time.
Additionally, Java doesn't have all the same features that the GAC and strongly-named assemblies bring. Jar Hell is the term for what can go wrong when linking/referencing external libraries.
As far as packaging/deployment is concerned:
it can be difficult to package up web applications in an EAR/WAR format that actually install and run in several different application servers (Glassfish, Websphere, etc).
deploying your Java app as a Windows service takes a lot more effort than in C#. Most of the recommendations I got for this involved a non-free 3rd party library
application configuration isn't nearly as easy as including an app.config file in your project. There is a java.util.Properties class, but it isn't as robust and finding the right spot to drop your .properties file can be confusing
There are no delegates in Java. Therefore, aside from all the benefits that delegates bring to the table, events work differently too. Instead of just hooking up a method, you need to implement an interface and attach that instead.
One thing that jumps out b/c it's on my interview list is that there is no "new" keyword analogue in Java for method hiding and there fore no compiler warning "you should put new here". Accidental method hiding when you meant to override leads to bugs.
(edit for example)
Example, B derives from A (using C# syntax, Java behaves same way last I checked but does not emit compiler warning). Does A's foo get called, or B's foo? (A's gets called, probably surprising the dev who implemented B).
class A
{
public void foo() {code}
}
class B:A
{
public void foo() {code}
}
void SomeMethod()
{
A a = new B(); // variable's type is declared as A, but assigned to an object of B.
a.foo();
}
Java doesn't have LINQ and the documentation is hell. User interfaces in Java are a pain to develop, you lose all the good things Microsoft gave us (WPF, WCF, etc...) but get hard - to - use, hardly documented "APIs".
The most harrasing difference to me when I switch to java it's the string declaration.
in C# string (most of the time)
in Java String
It's pretty simple, but trust me, it makes you lose so much time when you have the habit to s not S !
The one issue I've run into so far when working with Java coming from C# is Exceptions and Errors are different.
For example you cannot catch an out of memory error using catch(Exception e).
See the following for more details:
why-is-java-lang-outofmemoryerror-java-heap-space-not-caught
It's been so long since I've been in Java but the things I noticed right off the bat in application development was C# event model, C# drag and drop vs using Layout Managers in Swing (if your doing App dev), and exception handling with Java making sure you catch an exception and C# not required.
In response to your very direct question in your title:
"C# developers learning Java, what are the biggest differences one may overlook?"
A: The fact that Java is considerably slower on Windows.
A number of features were introduced into C# 3.0 which made me uneasy, such as object initializers, extension methods and implicitly typed variables. Now in C# 4.0 with things like the dynamic keyword I'm getting even more concerned.
I know that each of these features CAN be used in appropriate ways BUT in my view they make it easier for developers to make bad coding decisions and therefore write worse code. It seems to me that Microsoft are trying to win market share by making the coding easy and undemanding. Personally I prefer a language that is rigorous and places more demands on my coding standards and forces me to structure things in an OOP way.
Here are a few examples of my concerns for the features mentioned above:
Object constructors can do important logic that is not exposed to the consumer. This is in the control of the object developer. Object initializers take this control away and allow the consumer to make the decisions about which fields to initialize.
EDIT: I had not appreciated that you can mix constructor and initializer (my bad) but this starts to look messy to my mind and so I am still not convinced it is a step forward.
Allowing developers to extend built-in types using extension methods allows all and sundry to start adding their favourite pet methods to the string class, which can end up with a bewildering array of options, or requires more policing of coding standards to weed these out.
Allowing implicitly typed variables allows quick and dirty programming instead or properly OOP approaches, which can quickly become an unmanageable mess of vars all over your application.
Are my worries justified?
Object initializers simply allow the client to set properties immediately after construction, no control is relinquished as the caller must still ensure all of the constructor arguments are satisfied.
Personally I feel they add very little:
Person p1 = new Person("Fred");
p1.Age = 30;
p1.Height = 123;
Person p2 = new Person("Fred")
{
Age = 30;
Height = 123;
};
I know a lot of people dislike the 'var' keyword. I can understand why as it is an openly inviting abuse, but I do not mind it providing the type is blindingly obvious:
var p1 = new Person("Fred");
Person p2 = GetPerson();
In the second line above, the type is not obvious, despite the method name. I would use the type in this case.
Extension methods -- I would use very sparingly but they are very useful for extending the .NET types with convenience methods, especially IEnumerable, ICollection and String. String.IsNullOrEmpty() as an extension method is very nice, as it can be called on null references.
I do not think you need to worry, good developers will always use their tools with respect and bad developers will always find ways to misue their tools: limiting the toolset will not solve this problem.
You could limit the features of C# 3.0 your developers can use by writing the restrictions into your coding standards. Then when code is reviewed prior to check in, any code that breaches these rules should be spotted and the check in refused. One such case could well be extension methods.
Obviously, your developers will want to use the new features - all developers do. However, if you've got good, well documented reasons why they shouldn't be used, good developers will follow them. You should also be open to revising these rules as new information comes to light.
With VS 2008 you can specify which version of .NET you want to target (Right click over the solution and select Properties > Application). If you limit yourself to .NET 2.0 then you won't get any of the new features in .NET 3.5. Obviously this doesn't help if you want to use some of the features.
However, I think your fears over vars are unwarranted. C# is still as strongly typed as ever. Declaring something as var simply tells the compiler to pick the best type for this variable. The variable can't change type it's always an int or Person or whatever. Personally I follow the same rules as Paul Ruane; if the type is clear from the syntax then use a var; if not name the type explicitly.
I have seen your position expressed like this:
Build a development environment that
any fool can use and what you get is
many fools developing.
This is very true, but the rest of us look good by contrast. I regard this as a good thing. One of the funniest postings I have ever seen remarked that
VB should not be underestimated. It is an extremely powerful tool for
keeping idiots out of this [C++] newsgroup.
More seriously, whether or not a tools is dangerous depends on the wisdom of the wielder. the only way you can prevent folly is to prevent action. foreach looks innocuous but you can't even remove items as you iterate a collection because removing an item invalidates the iterator. You end up dumping them in favour of a classic for loop.
I think the only really justified issue in your bunch is overuse of extension methods. When important functionality is only accessible through extension methods, sometimes it's hard for everyone in a group to find out about and use that functionality.
Worrying about object initializers and the "var" keyword seems very nitpicky. Both are simple and predictable syntax that can be used to make code more readable, and it's not clear to me how you see them being "abused."
I suggest you address concerns like this through written, agreed-upon coding standards. If nobody can come up with good reasons to use new language features, then there's no need to use them, after all.
Object initializers are just fancy syntax. There is nothing the developer can do with them that he couldn't already do before - they do however save you a few lines of code.
If by "extend built in types" you mean extension methods - again, this is nothing new, just better syntax. The methods are static methods that appear as if they were members. The build in classes remain untouched.
Implicit typed variables are needed for Linq. I also use them with generics that have a lot of type parameters. But I'd agree that I wouldn't like to see them used exclusively.
Of course every feature can be abused but I think that these new features actually let you write code that is easier to read.
One big mitigating factor about var is that it can never move between scopes. It can not be a return type or a parameter type. This makes it far safer in my mind, as it is always tightly typed and always implementation detail of one method.
New features was introduced because Microsoft realized that they are absolutely necessary for implementing new language features. Like LINQ, for example. So you can use the same strategy:
1) know about those features,
2) do not use until you'd find it absolutely necessary for you.
If you really understand those features, I bet you'd feel it necessary pretty soon. :)
At least with "var" and intializers you're not really able to do anything new, it's just a new way to write things. Although it does look like object initializers compile to slightly different IL.
One angle that really blows my mind about extension methods is that you can put them on an interface. That means a class can inherit concrete code by implementing an interface. And since a class can implement multiple interfaces that means, in a roundabout sort of way, that C# now has something like multiple inheritance. So that's a new feature that should definitely be handled with care.
Are my worries justified?
No. This has been another edition of simple answers to simple questions.