Merge pull request #4025 from paszea/reflection_fqn

serialize fully qualified struct & enum name in schema binary
diff --git a/.gitignore b/.gitignore
index e07fbae..79c70d0 100755
--- a/.gitignore
+++ b/.gitignore
@@ -64,3 +64,4 @@
 build/VS2010/FlatBuffers.sdf
 build/VS2010/FlatBuffers.opensdf
 build/VS2010/ipch/**/*.ipch
+*.so
diff --git a/CMake/PackageDebian.cmake b/CMake/PackageDebian.cmake
new file mode 100644
index 0000000..ebe8931
--- /dev/null
+++ b/CMake/PackageDebian.cmake
@@ -0,0 +1,57 @@
+# ------------------- Debianization ---------------------
+if (UNIX)
+
+    # Set build environment
+    SET(CPACK_GENERATOR "TGZ;DEB")
+    SET(CPACK_SOURCE_TGZ "ON")
+
+    # Common package information
+    SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY
+        "FlatBuffers is an efficient cross platform serialization library for C++, with support for Java, C# and Go. It was created at Google specifically for game development and other performance-critical applications.")
+    SET(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/google/flatbuffers")
+    SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Vitaly Isaev <vitalyisaev2@gmail.com>")
+
+    # Derive package version from git
+    EXECUTE_PROCESS(
+        COMMAND date +%Y%m%d
+        OUTPUT_VARIABLE DATE
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+    )
+    EXECUTE_PROCESS(
+      COMMAND git describe
+      WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+      OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY
+      OUTPUT_STRIP_TRAILING_WHITESPACE
+    )
+    string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_DESCRIBE_DIRTY}")
+    string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GIT_DESCRIBE_DIRTY}")
+    string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GIT_DESCRIBE_DIRTY}")
+    string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+\\-([0-9]+).*" "\\1" VERSION_COMMIT "${GIT_DESCRIBE_DIRTY}")
+    SET(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
+    SET(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
+    SET(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH})
+    SET(CPACK_PACKAGE_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_COMMIT}")
+    SET(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}")
+
+    # Derive architecture
+    IF(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
+      FIND_PROGRAM(DPKG_CMD dpkg)
+      IF(NOT DPKG_CMD)
+        MESSAGE(STATUS "Can not find dpkg in your path, default to i386.")
+        SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE i386)
+      ENDIF(NOT DPKG_CMD)
+      EXECUTE_PROCESS(COMMAND "${DPKG_CMD}" --print-architecture
+        OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+        )
+    ENDIF(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
+
+    # Package name
+    SET(CPACK_DEBIAN_PACKAGE_NAME "flatbuffers")
+    SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE.txt)
+    SET(CPACK_PACKAGE_FILE_NAME 
+        "${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
+
+endif(UNIX)
+
+INCLUDE(CPack)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 81c9e58..ad01c21 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,6 +12,9 @@
        ON)
 option(FLATBUFFERS_BUILD_FLATHASH "Enable the build of flathash" ON)
 option(FLATBUFFERS_BUILD_GRPCTEST "Enable the build of grpctest" OFF)
+option(FLATBUFFERS_BUILD_SHAREDLIB
+       "Enable the build of the flatbuffers shared library"
+       OFF)
 
 if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
     message(WARNING
@@ -44,6 +47,7 @@
   src/idl_gen_fbs.cpp
   src/idl_gen_grpc.cpp
   src/flatc.cpp
+  grpc/src/compiler/schema_interface.h
   grpc/src/compiler/cpp_generator.h
   grpc/src/compiler/cpp_generator.cc
 )
@@ -163,6 +167,11 @@
   add_executable(flathash ${FlatHash_SRCS})
 endif()
 
+if(FLATBUFFERS_BUILD_SHAREDLIB)
+  add_library(flatbuffers_shared SHARED ${FlatBuffers_Library_SRCS})
+  set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers)
+endif()
+
 function(compile_flatbuffers_schema_to_cpp SRC_FBS)
   get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
   string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
@@ -211,6 +220,9 @@
   if(FLATBUFFERS_BUILD_FLATC)
     install(TARGETS flatc DESTINATION bin)
   endif()
+  if(FLATBUFFERS_BUILD_SHAREDLIB)
+    install(TARGETS flatbuffers_shared DESTINATION lib)
+  endif()
 endif()
 
 if(FLATBUFFERS_BUILD_TESTS)
@@ -222,3 +234,7 @@
 endif()
 
 include(CMake/BuildFlatBuffers.cmake)
+
+if(FLATBUFFERS_PACKAGE_DEBIAN)
+    include(CMake/PackageDebian.cmake)
+endif()
diff --git a/docs/source/JavaCsharpUsage.md b/docs/source/JavaCsharpUsage.md
index 3af9cfa..cc58f85 100755
--- a/docs/source/JavaCsharpUsage.md
+++ b/docs/source/JavaCsharpUsage.md
@@ -131,6 +131,36 @@
     monster.GetPos(preconstructedPos);
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+## Storing dictionaries in a FlatBuffer
+
+FlatBuffers doesn't support dictionaries natively, but there is support to
+emulate their behavior with vectors and binary search, which means you
+can have fast lookups directly from a FlatBuffer without having to unpack
+your data into a `Dictionary` or similar.
+
+To use it:
+-   Designate one of the fields in a table as they "key" field. You do this
+    by setting the `key` attribute on this field, e.g.
+    `name:string (key)`.
+    You may only have one key field, and it must be of string or scalar type.
+-   Write out tables of this type as usual, collect their offsets in an
+    array.
+-   Instead of calling standard generated method,
+    e.g.: `Monster.createTestarrayoftablesVector`,
+    call `CreateMySortedVectorOfTables` in C# or
+    `createSortedVectorOfTables` (from the `FlatBufferBuilder` object) in Java,
+    which will first sort all offsets such that the tables they refer to
+    are sorted by the key field, then serialize it.
+-   Now when you're accessing the FlatBuffer, you can use `LookupByKey`
+    to access elements of the vector, e.g.:
+    `Monster.lookupByKey(tablesVectorOffset, "Frodo", dataBuffer)`,
+    which returns an object of the corresponding table type,
+    or `null` if not found.
+    `LookupByKey` performs a binary search, so should have a similar speed to
+    `Dictionary`, though may be faster because of better caching. `LookupByKey`
+    only works if the vector has been sorted, it will likely not find elements
+    if it hasn't been sorted.
+
 ## Text parsing
 
 There currently is no support for parsing text (Schema's and JSON) directly
diff --git a/grpc/src/compiler/cpp_generator.cc b/grpc/src/compiler/cpp_generator.cc
index 9319c41..e8ad49e 100644
--- a/grpc/src/compiler/cpp_generator.cc
+++ b/grpc/src/compiler/cpp_generator.cc
@@ -67,7 +67,8 @@
 template<class T, size_t N>
 T *array_end(T (&array)[N]) { return array + N; }
 
-void PrintIncludes(Printer *printer, const std::vector<grpc::string>& headers, const Parameters &params) {
+void PrintIncludes(grpc_generator::Printer *printer, 
+                   const std::vector<grpc::string>& headers, const Parameters &params) {
   std::map<grpc::string, grpc::string> vars;
 
   vars["l"] = params.use_system_headers ? '<' : '"';
@@ -86,7 +87,7 @@
   }
 }
 
-grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) {
+grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters & /*params*/) {
   grpc::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
@@ -111,7 +112,7 @@
   return output;
 }
 
-grpc::string GetHeaderIncludes(File *file,
+grpc::string GetHeaderIncludes(grpc_generator::File *file,
                                const Parameters &params) {
   grpc::string output;
   {
@@ -154,7 +155,7 @@
 }
 
 void PrintHeaderClientMethodInterfaces(
-    Printer *printer, const Method *method,
+    grpc_generator::Printer *printer, const grpc_generator::Method *method,
     std::map<grpc::string, grpc::string> *vars, bool is_public) {
   (*vars)["Method"] = method->name();
   (*vars)["Request"] = method->input_type_name();
@@ -303,8 +304,8 @@
   }
 }
 
-void PrintHeaderClientMethod(Printer *printer,
-                             const Method *method,
+void PrintHeaderClientMethod(grpc_generator::Printer *printer,
+                             const grpc_generator::Method *method,
                              std::map<grpc::string, grpc::string> *vars,
                              bool is_public) {
   (*vars)["Method"] = method->name();
@@ -445,13 +446,13 @@
   }
 }
 
-void PrintHeaderClientMethodData(Printer *printer, const Method *method,
+void PrintHeaderClientMethodData(grpc_generator::Printer *printer, const grpc_generator::Method *method,
                                  std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
   printer->Print(*vars, "const ::grpc::RpcMethod rpcmethod_$Method$_;\n");
 }
 
-void PrintHeaderServerMethodSync(Printer *printer, const Method *method,
+void PrintHeaderServerMethodSync(grpc_generator::Printer *printer, const grpc_generator::Method *method,
                                  std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
   (*vars)["Request"] = method->input_type_name();
@@ -483,8 +484,8 @@
 }
 
 void PrintHeaderServerMethodAsync(
-    Printer *printer,
-    const Method *method,
+    grpc_generator::Printer *printer,
+    const grpc_generator::Method *method,
     std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
   (*vars)["Request"] = method->input_type_name();
@@ -599,8 +600,8 @@
 }
 
 void PrintHeaderServerMethodGeneric(
-    Printer *printer,
-    const Method *method,
+    grpc_generator::Printer *printer,
+    const grpc_generator::Method *method,
     std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
   (*vars)["Request"] = method->input_type_name();
@@ -669,8 +670,8 @@
   printer->Print(*vars, "};\n");
 }
 
-void PrintHeaderService(Printer *printer,
-                        const Service *service,
+void PrintHeaderService(grpc_generator::Printer *printer,
+                        const grpc_generator::Service *service,
                         std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Service"] = service->name();
 
@@ -764,7 +765,7 @@
   printer->Print("};\n");
 }
 
-grpc::string GetHeaderServices(File *file,
+grpc::string GetHeaderServices(grpc_generator::File *file,
                                const Parameters &params) {
   grpc::string output;
   {
@@ -795,7 +796,7 @@
   return output;
 }
 
-grpc::string GetHeaderEpilogue(File *file, const Parameters & /*params*/) {
+grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters & /*params*/) {
   grpc::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
@@ -821,7 +822,7 @@
   return output;
 }
 
-grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) {
+grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters & /*params*/) {
   grpc::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
@@ -845,7 +846,7 @@
   return output;
 }
 
-grpc::string GetSourceIncludes(File *file,
+grpc::string GetSourceIncludes(grpc_generator::File *file,
                                const Parameters &params) {
   grpc::string output;
   {
@@ -880,8 +881,8 @@
   return output;
 }
 
-void PrintSourceClientMethod(Printer *printer,
-                             const Method *method,
+void PrintSourceClientMethod(grpc_generator::Printer *printer,
+                             const grpc_generator::Method *method,
                              std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
   (*vars)["Request"] = method->input_type_name();
@@ -981,8 +982,8 @@
   }
 }
 
-void PrintSourceServerMethod(Printer *printer,
-                             const Method *method,
+void PrintSourceServerMethod(grpc_generator::Printer *printer,
+                             const grpc_generator::Method *method,
                              std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
   (*vars)["Request"] = method->input_type_name();
@@ -1040,8 +1041,8 @@
   }
 }
 
-void PrintSourceService(Printer *printer,
-                        const Service *service,
+void PrintSourceService(grpc_generator::Printer *printer,
+                        const grpc_generator::Service *service,
                         std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Service"] = service->name();
 
@@ -1153,7 +1154,7 @@
   }
 }
 
-grpc::string GetSourceServices(File *file,
+grpc::string GetSourceServices(grpc_generator::File *file,
                                const Parameters &params) {
   grpc::string output;
   {
@@ -1182,7 +1183,7 @@
   return output;
 }
 
-grpc::string GetSourceEpilogue(File *file, const Parameters & /*params*/) {
+grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters & /*params*/) {
   grpc::string temp;
 
   if (!file->package().empty()) {
diff --git a/grpc/src/compiler/cpp_generator.h b/grpc/src/compiler/cpp_generator.h
index 953ddfd..a4adee7 100644
--- a/grpc/src/compiler/cpp_generator.h
+++ b/grpc/src/compiler/cpp_generator.h
@@ -41,16 +41,7 @@
 #include <memory>
 #include <vector>
 
-#ifndef GRPC_CUSTOM_STRING
-#include <string>
-#define GRPC_CUSTOM_STRING std::string
-#endif
-
-namespace grpc {
-
-typedef GRPC_CUSTOM_STRING string;
-
-}  // namespace grpc
+#include "src/compiler/schema_interface.h"
 
 namespace grpc_cpp_generator {
 
@@ -64,83 +55,29 @@
   grpc::string grpc_search_path;
 };
 
-// An abstract interface representing a method.
-struct Method {
-  virtual ~Method() {}
-
-  virtual grpc::string name() const = 0;
-
-  virtual grpc::string input_type_name() const = 0;
-  virtual grpc::string output_type_name() const = 0;
-
-  virtual bool NoStreaming() const = 0;
-  virtual bool ClientOnlyStreaming() const = 0;
-  virtual bool ServerOnlyStreaming() const = 0;
-  virtual bool BidiStreaming() const = 0;
-};
-
-// An abstract interface representing a service.
-struct Service {
-  virtual ~Service() {}
-
-  virtual grpc::string name() const = 0;
-
-  virtual int method_count() const = 0;
-  virtual std::unique_ptr<const Method> method(int i) const = 0;
-};
-
-struct Printer {
-  virtual ~Printer() {}
-
-  virtual void Print(const std::map<grpc::string, grpc::string> &vars,
-                     const char *template_string) = 0;
-  virtual void Print(const char *string) = 0;
-  virtual void Indent() = 0;
-  virtual void Outdent() = 0;
-};
-
-// An interface that allows the source generated to be output using various
-// libraries/idls/serializers.
-struct File {
-  virtual ~File() {}
-
-  virtual grpc::string filename() const = 0;
-  virtual grpc::string filename_without_ext() const = 0;
-  virtual grpc::string message_header_ext() const = 0;
-  virtual grpc::string service_header_ext() const = 0;
-  virtual grpc::string package() const = 0;
-  virtual std::vector<grpc::string> package_parts() const = 0;
-  virtual grpc::string additional_headers() const = 0;
-
-  virtual int service_count() const = 0;
-  virtual std::unique_ptr<const Service> service(int i) const = 0;
-
-  virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
-};
-
 // Return the prologue of the generated header file.
-grpc::string GetHeaderPrologue(File *file, const Parameters &params);
+grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters &params);
 
 // Return the includes needed for generated header file.
-grpc::string GetHeaderIncludes(File *file, const Parameters &params);
+grpc::string GetHeaderIncludes(grpc_generator::File *file, const Parameters &params);
 
 // Return the includes needed for generated source file.
-grpc::string GetSourceIncludes(File *file, const Parameters &params);
+grpc::string GetSourceIncludes(grpc_generator::File *file, const Parameters &params);
 
 // Return the epilogue of the generated header file.
-grpc::string GetHeaderEpilogue(File *file, const Parameters &params);
+grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters &params);
 
 // Return the prologue of the generated source file.
-grpc::string GetSourcePrologue(File *file, const Parameters &params);
+grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters &params);
 
 // Return the services for generated header file.
-grpc::string GetHeaderServices(File *file, const Parameters &params);
+grpc::string GetHeaderServices(grpc_generator::File *file, const Parameters &params);
 
 // Return the services for generated source file.
-grpc::string GetSourceServices(File *file, const Parameters &params);
+grpc::string GetSourceServices(grpc_generator::File *file, const Parameters &params);
 
 // Return the epilogue of the generated source file.
-grpc::string GetSourceEpilogue(File *file, const Parameters &params);
+grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters &params);
 
 }  // namespace grpc_cpp_generator
 
diff --git a/grpc/src/compiler/schema_interface.h b/grpc/src/compiler/schema_interface.h
new file mode 100644
index 0000000..332a51a
--- /dev/null
+++ b/grpc/src/compiler/schema_interface.h
@@ -0,0 +1,108 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
+#define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
+
+ #include <memory>
+ #include <vector>
+
+ #ifndef GRPC_CUSTOM_STRING
+ #include <string>
+ #define GRPC_CUSTOM_STRING std::string
+ #endif
+
+namespace grpc {
+
+  typedef GRPC_CUSTOM_STRING string;
+
+}  // namespace grpc
+
+namespace grpc_generator {
+
+  // An abstract interface representing a method.
+  struct Method {
+    virtual ~Method() {}
+
+    virtual grpc::string name() const = 0;
+
+    virtual grpc::string input_type_name() const = 0;
+    virtual grpc::string output_type_name() const = 0;
+
+    virtual bool NoStreaming() const = 0;
+    virtual bool ClientOnlyStreaming() const = 0;
+    virtual bool ServerOnlyStreaming() const = 0;
+    virtual bool BidiStreaming() const = 0;
+  };
+
+  // An abstract interface representing a service.
+  struct Service {
+    virtual ~Service() {}
+
+    virtual grpc::string name() const = 0;
+
+    virtual int method_count() const = 0;
+    virtual std::unique_ptr<const Method> method(int i) const = 0;
+  };
+
+  struct Printer {
+    virtual ~Printer() {}
+
+    virtual void Print(const std::map<grpc::string, grpc::string> &vars,
+                       const char *template_string) = 0;
+    virtual void Print(const char *string) = 0;
+    virtual void Indent() = 0;
+    virtual void Outdent() = 0;
+  };
+
+  // An interface that allows the source generated to be output using various
+  // libraries/idls/serializers.
+  struct File {
+    virtual ~File() {}
+
+    virtual grpc::string filename() const = 0;
+    virtual grpc::string filename_without_ext() const = 0;
+    virtual grpc::string message_header_ext() const = 0;
+    virtual grpc::string service_header_ext() const = 0;
+    virtual grpc::string package() const = 0;
+    virtual std::vector<grpc::string> package_parts() const = 0;
+    virtual grpc::string additional_headers() const = 0;
+
+    virtual int service_count() const = 0;
+    virtual std::unique_ptr<const Service> service(int i) const = 0;
+
+    virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
+  };
+} // namespace grpc_generator
+
+#endif  // GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h
index 4644f9c..aefde0e 100644
--- a/include/flatbuffers/flatbuffers.h
+++ b/include/flatbuffers/flatbuffers.h
@@ -255,7 +255,7 @@
 
 public:
   VectorIterator(const uint8_t *data, uoffset_t i) :
-      data_(data + IndirectHelper<T>::element_stride * i) {};
+      data_(data + IndirectHelper<T>::element_stride * i) {}
   VectorIterator(const VectorIterator &other) : data_(other.data_) {}
   #ifndef FLATBUFFERS_CPP98_STL
   VectorIterator(VectorIterator &&other) : data_(std::move(other.data_)) {}
@@ -1436,11 +1436,6 @@
     return ReadScalar<T>(&data_[o]);
   }
 
-  template<typename T> T GetPointer(uoffset_t o) const {
-    auto p = &data_[o];
-    return reinterpret_cast<T>(p + ReadScalar<uoffset_t>(p));
-  }
-
   template<typename T> T GetStruct(uoffset_t o) const {
     return reinterpret_cast<T>(&data_[o]);
   }
diff --git a/include/flatbuffers/util.h b/include/flatbuffers/util.h
index baf5bdd..c6755ab 100644
--- a/include/flatbuffers/util.h
+++ b/include/flatbuffers/util.h
@@ -95,20 +95,20 @@
 }
 
 // Portable implementation of strtoll().
-inline int64_t StringToInt(const char *str, int base = 10) {
+inline int64_t StringToInt(const char *str, char **endptr = nullptr, int base = 10) {
   #ifdef _MSC_VER
-    return _strtoi64(str, nullptr, base);
+    return _strtoi64(str, endptr, base);
   #else
-    return strtoll(str, nullptr, base);
+    return strtoll(str, endptr, base);
   #endif
 }
 
 // Portable implementation of strtoull().
-inline int64_t StringToUInt(const char *str, int base = 10) {
+inline int64_t StringToUInt(const char *str, char **endptr = nullptr, int base = 10) {
   #ifdef _MSC_VER
-    return _strtoui64(str, nullptr, base);
+    return _strtoui64(str, endptr, base);
   #else
-    return strtoull(str, nullptr, base);
+    return strtoull(str, endptr, base);
   #endif
 }
 
diff --git a/java/com/google/flatbuffers/FlatBufferBuilder.java b/java/com/google/flatbuffers/FlatBufferBuilder.java
index f69fbcf..fd4b729 100644
--- a/java/com/google/flatbuffers/FlatBufferBuilder.java
+++ b/java/com/google/flatbuffers/FlatBufferBuilder.java
@@ -390,6 +390,31 @@
     }
 
    /**
+     * Create a vector of tables.
+     *
+     * @param offsets Offsets of the tables.
+     * @return Returns offset of the vector.
+     */
+    public int createVectorOfTables(int[] offsets) {
+        notNested();
+        startVector(Constants.SIZEOF_INT, offsets.length, Constants.SIZEOF_INT);
+        for(int i = offsets.length - 1; i >= 0; i--) addOffset(offsets[i]);
+        return endVector();
+    }
+
+    /**
+     * Create a vector of sorted by the key tables.
+     *
+     * @param obj Instance of the table subclass.
+     * @param offsets Offsets of the tables.
+     * @return Returns offset of the sorted vector.
+     */
+    public <T extends Table> int createSortedVectorOfTables(T obj, int[] offsets) {
+        obj.sortTables(offsets, bb);
+        return createVectorOfTables(offsets);
+    }
+	
+   /**
     * Encode the string `s` in the buffer using UTF-8.  If {@code s} is
     * already a {@link CharBuffer}, this method is allocation free.
     *
diff --git a/java/com/google/flatbuffers/Table.java b/java/com/google/flatbuffers/Table.java
index 4087654..b853842 100644
--- a/java/com/google/flatbuffers/Table.java
+++ b/java/com/google/flatbuffers/Table.java
@@ -37,6 +37,12 @@
       return Charset.forName("UTF-8").newDecoder();
     }
   };
+  public final static ThreadLocal<Charset> UTF8_CHARSET = new ThreadLocal<Charset>() {
+    @Override
+    protected Charset initialValue() {
+      return Charset.forName("UTF-8");
+    }
+  };
   private final static ThreadLocal<CharBuffer> CHAR_BUFFER = new ThreadLocal<CharBuffer>();
   /** Used to hold the position of the `bb` buffer. */
   protected int bb_pos;
@@ -61,6 +67,11 @@
     return vtable_offset < bb.getShort(vtable) ? bb.getShort(vtable + vtable_offset) : 0;
   }
 
+  protected static int __offset(int vtable_offset, int offset, ByteBuffer bb) {
+    int vtable = bb.array().length - offset;
+    return bb.getShort(vtable + vtable_offset - bb.getInt(vtable)) + vtable;
+  }
+
   /**
    * Retrieve a relative offset.
    *
@@ -71,6 +82,10 @@
     return offset + bb.getInt(offset);
   }
 
+  protected static int __indirect(int offset, ByteBuffer bb) {
+    return offset + bb.getInt(offset);
+  }
+
   /**
    * Create a Java `String` from UTF-8 data stored inside the FlatBuffer.
    *
@@ -188,6 +203,76 @@
     }
     return true;
   }
+
+  /**
+   * Sort tables by the key.
+   *
+   * @param offsets An 'int' indexes of the tables into the bb.
+   * @param bb A {@code ByteBuffer} to get the tables.
+   */
+  protected void sortTables(int[] offsets, final ByteBuffer bb) {
+    Integer[] off = new Integer[offsets.length];
+    for (int i = 0; i < offsets.length; i++) off[i] = offsets[i];
+    java.util.Arrays.sort(off, new java.util.Comparator<Integer>() {
+      public int compare(Integer o1, Integer o2) {
+        return keysCompare(o1, o2, bb);
+      }
+    });
+    for (int i = 0; i < offsets.length; i++) offsets[i] = off[i];
+  }
+
+  /**
+   * Compare two tables by the key.
+   *
+   * @param o1 An 'Integer' index of the first key into the bb.
+   * @param o2 An 'Integer' index of the second key into the bb.
+   * @param bb A {@code ByteBuffer} to get the keys.
+   */
+  protected int keysCompare(Integer o1, Integer o2, ByteBuffer bb) { return 0; }
+
+  /**
+   * Compare two strings in the buffer.
+   *
+   * @param offset_1 An 'int' index of the first string into the bb.
+   * @param offset_2 An 'int' index of the second string into the bb.
+   * @param bb A {@code ByteBuffer} to get the strings.
+   */
+  protected static int compareStrings(int offset_1, int offset_2, ByteBuffer bb) {
+    offset_1 += bb.getInt(offset_1);
+    offset_2 += bb.getInt(offset_2);
+    int len_1 = bb.getInt(offset_1);
+    int len_2 = bb.getInt(offset_2);
+    int startPos_1 = offset_1 + SIZEOF_INT;
+    int startPos_2 = offset_2 + SIZEOF_INT;
+    int len = Math.min(len_1, len_2);
+    byte[] bbArray = bb.array();
+    for(int i = 0; i < len; i++) {
+      if (bbArray[i + startPos_1] != bbArray[i + startPos_2])
+        return bbArray[i + startPos_1] - bbArray[i + startPos_2];
+    }
+    return len_1 - len_2;
+  }
+
+  /**
+   * Compare string from the buffer with the 'String' object.
+   *
+   * @param offset_1 An 'int' index of the first string into the bb.
+   * @param key Second string as a byte array.
+   * @param bb A {@code ByteBuffer} to get the first string.
+   */
+  protected static int compareStrings(int offset_1, byte[] key, ByteBuffer bb) {
+    offset_1 += bb.getInt(offset_1);
+    int len_1 = bb.getInt(offset_1);
+    int len_2 = key.length;
+    int startPos_1 = offset_1 + Constants.SIZEOF_INT;
+    int len = Math.min(len_1, len_2);
+    byte[] bbArray = bb.array();
+    for (int i = 0; i < len; i++) {
+      if (bbArray[i + startPos_1] != key[i])
+        return bbArray[i + startPos_1] - key[i];
+    }
+    return len_1 - len_2;
+  }
 }
 
 /// @endcond
diff --git a/net/FlatBuffers/ByteBuffer.cs b/net/FlatBuffers/ByteBuffer.cs
index 5fa1ac7..37a2c7e 100755
--- a/net/FlatBuffers/ByteBuffer.cs
+++ b/net/FlatBuffers/ByteBuffer.cs
@@ -14,7 +14,20 @@
  * limitations under the License.
  */
 
-//#define UNSAFE_BYTEBUFFER  // uncomment this line to use faster ByteBuffer
+// There are 2 #defines that have an impact on performance of this ByteBuffer implementation
+//
+//      UNSAFE_BYTEBUFFER 
+//          This will use unsafe code to manipulate the underlying byte array. This
+//          can yield a reasonable performance increase.
+//
+//      BYTEBUFFER_NO_BOUNDS_CHECK
+//          This will disable the bounds check asserts to the byte array. This can
+//          yield a small performance gain in normal code..
+//
+// Using UNSAFE_BYTEBUFFER and BYTEBUFFER_NO_BOUNDS_CHECK together can yield a
+// performance gain of ~15% for some operations, however doing so is potentially 
+// dangerous. Do so at your own risk!
+//
 
 using System;
 
@@ -22,9 +35,6 @@
 {
     /// <summary>
     /// Class to mimic Java's ByteBuffer which is used heavily in Flatbuffers.
-    /// If your execution environment allows unsafe code, you should enable
-    /// unsafe code in your project and #define UNSAFE_BYTEBUFFER to use a
-    /// MUCH faster version of ByteBuffer.
     /// </summary>
     public class ByteBuffer
     {
@@ -126,11 +136,14 @@
         }
 #endif // !UNSAFE_BYTEBUFFER
 
+
         private void AssertOffsetAndLength(int offset, int length)
         {
+            #if !BYTEBUFFER_NO_BOUNDS_CHECK
             if (offset < 0 ||
                 offset > _buffer.Length - length)
                 throw new ArgumentOutOfRangeException();
+            #endif
         }
 
         public void PutSbyte(int offset, sbyte value)
@@ -200,7 +213,6 @@
         public unsafe void PutUlong(int offset, ulong value)
         {
             AssertOffsetAndLength(offset, sizeof(ulong));
-
             fixed (byte* ptr = _buffer)
             {
                 *(ulong*)(ptr + offset) = BitConverter.IsLittleEndian
diff --git a/net/FlatBuffers/FlatBufferBuilder.cs b/net/FlatBuffers/FlatBufferBuilder.cs
index 8c57abe..b6701df 100644
--- a/net/FlatBuffers/FlatBufferBuilder.cs
+++ b/net/FlatBuffers/FlatBufferBuilder.cs
@@ -296,6 +296,18 @@
             return new VectorOffset(Offset);
         }
 
+        /// <summary>
+        /// Creates a vector of tables.
+        /// </summary>
+        /// <param name="offsets">Offsets of the tables.</param>
+        public VectorOffset CreateVectorOfTables<T>(Offset<T>[] offsets) where T : struct
+        {
+            NotNested();
+            StartVector(sizeof(int), offsets.Length, sizeof(int));
+            for (int i = offsets.Length - 1; i >= 0; i--) AddOffset(offsets[i].Value);
+            return EndVector();
+        }
+
         /// @cond FLATBUFFERS_INTENRAL
         public void Nested(int obj)
         {
diff --git a/net/FlatBuffers/FlatBuffers.csproj b/net/FlatBuffers/FlatBuffers.csproj
index 3ae938a..2a0cf99 100644
--- a/net/FlatBuffers/FlatBuffers.csproj
+++ b/net/FlatBuffers/FlatBuffers.csproj
@@ -37,6 +37,7 @@
     <Compile Include="ByteBuffer.cs" />
     <Compile Include="FlatBufferBuilder.cs" />
     <Compile Include="FlatBufferConstants.cs" />
+    <Compile Include="IFlatbufferObject.cs" />
     <Compile Include="Offset.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Struct.cs" />
diff --git a/net/FlatBuffers/IFlatbufferObject.cs b/net/FlatBuffers/IFlatbufferObject.cs
new file mode 100644
index 0000000..6a15aba
--- /dev/null
+++ b/net/FlatBuffers/IFlatbufferObject.cs
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace FlatBuffers
+{
+    /// <summary>
+    /// This is the base for both structs and tables.
+    /// </summary>
+    public interface IFlatbufferObject
+    {
+        void __init(int _i, ByteBuffer _bb);
+
+        ByteBuffer ByteBuffer { get; }
+    }
+}
diff --git a/net/FlatBuffers/Offset.cs b/net/FlatBuffers/Offset.cs
index a1524df..2b17cec 100644
--- a/net/FlatBuffers/Offset.cs
+++ b/net/FlatBuffers/Offset.cs
@@ -19,7 +19,7 @@
     /// <summary>
     /// Offset class for typesafe assignments.
     /// </summary>
-    public struct Offset<T> where T : class
+    public struct Offset<T> where T : struct
     {
         public int Value;
         public Offset(int value)
diff --git a/net/FlatBuffers/Struct.cs b/net/FlatBuffers/Struct.cs
index ab16f28..61da32f 100644
--- a/net/FlatBuffers/Struct.cs
+++ b/net/FlatBuffers/Struct.cs
@@ -19,9 +19,9 @@
     /// <summary>
     /// All structs in the generated code derive from this class, and add their own accessors.
     /// </summary>
-    public abstract class Struct
+    public struct Struct
     {
-        protected int bb_pos;
-        protected ByteBuffer bb;
+        public int bb_pos;
+        public ByteBuffer bb;
     }
-}
\ No newline at end of file
+}
diff --git a/net/FlatBuffers/Table.cs b/net/FlatBuffers/Table.cs
index bd5e364..55182b3 100644
--- a/net/FlatBuffers/Table.cs
+++ b/net/FlatBuffers/Table.cs
@@ -20,31 +20,42 @@
 namespace FlatBuffers
 {
     /// <summary>
-    /// All tables in the generated code derive from this class, and add their own accessors.
+    /// All tables in the generated code derive from this struct, and add their own accessors.
     /// </summary>
-    public abstract class Table
+    public struct Table
     {
-        protected int bb_pos;
-        protected ByteBuffer bb;
+        public int bb_pos;
+        public ByteBuffer bb;
 
         public ByteBuffer ByteBuffer { get { return bb; } }
 
         // Look up a field in the vtable, return an offset into the object, or 0 if the field is not
         // present.
-        protected int __offset(int vtableOffset)
+        public int __offset(int vtableOffset)
         {
             int vtable = bb_pos - bb.GetInt(bb_pos);
             return vtableOffset < bb.GetShort(vtable) ? (int)bb.GetShort(vtable + vtableOffset) : 0;
         }
 
+        public static int __offset(int vtableOffset, int offset, ByteBuffer bb)
+        {
+            int vtable = bb.Length - offset;
+            return (int)bb.GetShort(vtable + vtableOffset - bb.GetInt(vtable)) + vtable;
+        }
+
         // Retrieve the relative offset stored at "offset"
-        protected int __indirect(int offset)
+        public int __indirect(int offset)
+        {
+            return offset + bb.GetInt(offset);
+        }
+
+        public static int __indirect(int offset, ByteBuffer bb)
         {
             return offset + bb.GetInt(offset);
         }
 
         // Create a .NET String from UTF-8 data stored inside the flatbuffer.
-        protected string __string(int offset)
+        public string __string(int offset)
         {
             offset += bb.GetInt(offset);
             var len = bb.GetInt(offset);
@@ -53,7 +64,7 @@
         }
 
         // Get the length of a vector whose offset is stored at "offset" in this object.
-        protected int __vector_len(int offset)
+        public int __vector_len(int offset)
         {
             offset += bb_pos;
             offset += bb.GetInt(offset);
@@ -61,7 +72,7 @@
         }
 
         // Get the start of data of a vector whose offset is stored at "offset" in this object.
-        protected int __vector(int offset)
+        public int __vector(int offset)
         {
             offset += bb_pos;
             return offset + bb.GetInt(offset) + sizeof(int);  // data starts after the length
@@ -70,7 +81,8 @@
         // Get the data of a vector whoses offset is stored at "offset" in this object as an
         // ArraySegment&lt;byte&gt;. If the vector is not present in the ByteBuffer,
         // then a null value will be returned.
-        protected ArraySegment<byte>? __vector_as_arraysegment(int offset) {
+        public ArraySegment<byte>? __vector_as_arraysegment(int offset)
+        {
             var o = this.__offset(offset);
             if (0 == o)
             {
@@ -83,15 +95,15 @@
         }
 
         // Initialize any Table-derived type to point to the union at the given offset.
-        protected TTable __union<TTable>(TTable t, int offset) where TTable : Table
+        public T __union<T>(int offset) where T : struct, IFlatbufferObject
         {
             offset += bb_pos;
-            t.bb_pos = offset + bb.GetInt(offset);
-            t.bb = bb;
+            T t = new T();
+            t.__init(offset + bb.GetInt(offset), bb);
             return t;
         }
 
-        protected static bool __has_identifier(ByteBuffer bb, string ident)
+        public static bool __has_identifier(ByteBuffer bb, string ident)
         {
             if (ident.Length != FlatBufferConstants.FileIdentifierLength)
                 throw new ArgumentException("FlatBuffers: file identifier must be length " + FlatBufferConstants.FileIdentifierLength, "ident");
@@ -104,6 +116,38 @@
             return true;
         }
 
+        // Compare strings in the ByteBuffer.
+        public static int CompareStrings(int offset_1, int offset_2, ByteBuffer bb)
+        {
+            offset_1 += bb.GetInt(offset_1);
+            offset_2 += bb.GetInt(offset_2);
+            var len_1 = bb.GetInt(offset_1);
+            var len_2 = bb.GetInt(offset_2);
+            var startPos_1 = offset_1 + sizeof(int);
+            var startPos_2 = offset_2 + sizeof(int);
+            var len = Math.Min(len_1, len_2);
+            byte[] bbArray = bb.Data;
+            for(int i = 0; i < len; i++) {
+                if (bbArray[i + startPos_1] != bbArray[i + startPos_2])
+                    return bbArray[i + startPos_1] - bbArray[i + startPos_2];
+            }
+            return len_1 - len_2;
+        }
 
+        // Compare string from the ByteBuffer with the string object
+        public static int CompareStrings(int offset_1, byte[] key, ByteBuffer bb)
+        {
+            offset_1 += bb.GetInt(offset_1);
+            var len_1 = bb.GetInt(offset_1);
+            var len_2 = key.Length;
+            var startPos_1 = offset_1 + sizeof(int);
+            var len = Math.Min(len_1, len_2);
+            byte[] bbArray = bb.Data;
+            for (int i = 0; i < len; i++) {
+                if (bbArray[i + startPos_1] != key[i])
+                    return bbArray[i + startPos_1] - key[i];
+            }
+            return len_1 - len_2;
+        }
     }
 }
diff --git a/src/flatc.cpp b/src/flatc.cpp
index ba3fb19..5ca7ab3 100644
--- a/src/flatc.cpp
+++ b/src/flatc.cpp
@@ -243,7 +243,7 @@
             goto found;
           }
         }
-        Error("unknown commandline argument" + arg, true);
+        Error("unknown commandline argument: " + arg, true);
         found:;
       }
     } else {
diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp
index edb14cc..74a6bf9 100644
--- a/src/idl_gen_cpp.cpp
+++ b/src/idl_gen_cpp.cpp
@@ -333,15 +333,15 @@
     return (opts.scoped_enums ? "enum class " : "enum ") + enum_def.name;
   }
 
-  static std::string GenEnumVal(const EnumDef &enum_def,
-                                const std::string &enum_val,
-                                const IDLOptions &opts) {
+  static std::string GenEnumValDecl(const EnumDef &enum_def,
+                                   const std::string &enum_val,
+                                   const IDLOptions &opts) {
     return opts.prefixed_enums ? enum_def.name + "_" + enum_val : enum_val;
   }
 
-  static std::string GetEnumVal(const EnumDef &enum_def,
-                                const EnumVal &enum_val,
-                                const IDLOptions &opts) {
+  static std::string GetEnumValUse(const EnumDef &enum_def,
+                                   const EnumVal &enum_val,
+                                   const IDLOptions &opts) {
     if (opts.scoped_enums) {
       return enum_def.name + "::" + enum_val.name;
     } else if (opts.prefixed_enums) {
@@ -396,7 +396,7 @@
          ++it) {
       auto &ev = **it;
       GenComment(ev.doc_comment, code_ptr, nullptr, "  ");
-      code += "  " + GenEnumVal(enum_def, ev.name, parser_.opts) + " = ";
+      code += "  " + GenEnumValDecl(enum_def, ev.name, parser_.opts) + " = ";
       code += NumToString(ev.value) + ",\n";
       minv = !minv || minv->value > ev.value ? &ev : minv;
       maxv = !maxv || maxv->value < ev.value ? &ev : maxv;
@@ -406,15 +406,15 @@
       assert(minv && maxv);
       if (enum_def.attributes.Lookup("bit_flags")) {
         if (minv->value != 0)  // If the user didn't defined NONE value
-          code += "  " + GenEnumVal(enum_def, "NONE", parser_.opts) + " = 0,\n";
+          code += "  " + GenEnumValDecl(enum_def, "NONE", parser_.opts) + " = 0,\n";
         if (maxv->value != anyv)  // If the user didn't defined ANY value
-          code += "  " + GenEnumVal(enum_def, "ANY", parser_.opts) + " = " +
+          code += "  " + GenEnumValDecl(enum_def, "ANY", parser_.opts) + " = " +
                   NumToString(anyv) + "\n";
       } else {  // MIN & MAX are useless for bit_flags
-        code += "  " + GenEnumVal(enum_def, "MIN", parser_.opts) + " = ";
-        code += GenEnumVal(enum_def, minv->name, parser_.opts) + ",\n";
-        code += "  " + GenEnumVal(enum_def, "MAX", parser_.opts) + " = ";
-        code += GenEnumVal(enum_def, maxv->name, parser_.opts) + "\n";
+        code += "  " + GenEnumValDecl(enum_def, "MIN", parser_.opts) + " = ";
+        code += GenEnumValDecl(enum_def, minv->name, parser_.opts) + ",\n";
+        code += "  " + GenEnumValDecl(enum_def, "MAX", parser_.opts) + " = ";
+        code += GenEnumValDecl(enum_def, maxv->name, parser_.opts) + "\n";
       }
     }
     code += "};\n";
@@ -429,7 +429,7 @@
       code += "  " + enum_def.name + " type;\n\n";
       code += "  flatbuffers::NativeTable *table;\n";
       code += "  " + enum_def.name + "Union() : type(";
-      code += GenEnumVal(enum_def, "NONE", parser_.opts);
+      code += GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"), parser_.opts);
       code += "), table(nullptr) {}\n";
       code += "  " + enum_def.name + "Union(const ";
       code += enum_def.name + "Union &);\n";
@@ -445,7 +445,7 @@
           auto native_name = NativeName(WrapInNameSpace(*ev.struct_def));
           code += "  " + native_name + " *As";
           code += ev.name + "() { return type == ";
-          code += GetEnumVal(enum_def, ev, parser_.opts);
+          code += GetEnumValUse(enum_def, ev, parser_.opts);
           code += " ? reinterpret_cast<" + native_name;
           code += " *>(table) : nullptr; }\n";
         }
@@ -478,7 +478,7 @@
       code += "()[static_cast<int>(e)";
       if (enum_def.vals.vec.front()->value) {
         code += " - static_cast<int>(";
-        code += GetEnumVal(enum_def, *enum_def.vals.vec.front(), parser_.opts) +
+        code += GetEnumValUse(enum_def, *enum_def.vals.vec.front(), parser_.opts) +
                 ")";
       }
       code += "]; }\n\n";
@@ -500,7 +500,7 @@
     for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
          ++it) {
       auto &ev = **it;
-      code += "    case " + GetEnumVal(enum_def, ev, parser_.opts);
+      code += "    case " + GetEnumValUse(enum_def, ev, parser_.opts);
       if (!ev.value) {
         code += ": return true;\n";  // "NONE" enum value.
       } else {
@@ -518,7 +518,7 @@
       for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
            ++it) {
         auto &ev = **it;
-        code += "    case " + GetEnumVal(enum_def, ev, parser_.opts);
+        code += "    case " + GetEnumValUse(enum_def, ev, parser_.opts);
         if (!ev.value) {
           code += ": return nullptr;\n";  // "NONE" enum value.
         } else {
@@ -533,7 +533,7 @@
       for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
            ++it) {
         auto &ev = **it;
-        code += "    case " + GetEnumVal(enum_def, ev, parser_.opts);
+        code += "    case " + GetEnumValUse(enum_def, ev, parser_.opts);
         if (!ev.value) {
           code += ": return 0;\n";  // "NONE" enum value.
         } else {
@@ -553,7 +553,7 @@
            ++it) {
         auto &ev = **it;
         if (ev.value) {
-          code += "    case " + GenEnumVal(enum_def, ev.name, parser_.opts);
+          code += "    case " + GetEnumValUse(enum_def, ev, parser_.opts);
           code += ": delete reinterpret_cast<";
           code += NativeName(WrapInNameSpace(*ev.struct_def));
           code += " *>(table); break;\n";
@@ -613,7 +613,7 @@
       if (ev) {
         code += WrapInNameSpace(
             field.value.type.enum_def->defined_namespace,
-            GetEnumVal(*field.value.type.enum_def, *ev, parser_.opts));
+            GetEnumValUse(*field.value.type.enum_def, *ev, parser_.opts));
       } else {
         code += GenUnderlyingCast(field, true, field.value.constant);
       }
diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp
index 7e8e8c5..30899d4 100644
--- a/src/idl_gen_general.cpp
+++ b/src/idl_gen_general.cpp
@@ -76,24 +76,28 @@
   IDLOptions::Language language;
   // Whether function names in the language typically start with uppercase.
   bool first_camel_upper;
-  const char *file_extension;
-  const char *string_type;
-  const char *bool_type;
-  const char *open_curly;
-  const char *const_decl;
-  const char *unsubclassable_decl;
-  const char *enum_decl;
-  const char *enum_separator;
-  const char *getter_prefix;
-  const char *getter_suffix;
-  const char *inheritance_marker;
-  const char *namespace_ident;
-  const char *namespace_begin;
-  const char *namespace_end;
-  const char *set_bb_byteorder;
-  const char *get_bb_position;
-  const char *get_fbb_offset;
-  const char *includes;
+  std::string file_extension;
+  std::string string_type;
+  std::string bool_type;
+  std::string open_curly;
+  std::string accessor_type;
+  std::string const_decl;
+  std::string unsubclassable_decl;
+  std::string enum_decl;
+  std::string enum_separator;
+  std::string getter_prefix;
+  std::string getter_suffix;
+  std::string inheritance_marker;
+  std::string namespace_ident;
+  std::string namespace_begin;
+  std::string namespace_end;
+  std::string set_bb_byteorder;
+  std::string get_bb_position;
+  std::string get_fbb_offset;
+  std::string accessor_prefix;
+  std::string accessor_prefix_static;
+  std::string optional_suffix;
+  std::string includes;
   CommentConfig comment_config;
 };
 
@@ -105,6 +109,7 @@
     "String",
     "boolean ",
     " {\n",
+    "class ",
     " final ",
     "final ",
     "final class ",
@@ -118,6 +123,9 @@
     "_bb.order(ByteOrder.LITTLE_ENDIAN); ",
     "position()",
     "offset()",
+    "",
+    "",
+    "",
     "import java.nio.*;\nimport java.lang.*;\nimport java.util.*;\n"
       "import com.google.flatbuffers.*;\n\n@SuppressWarnings(\"unused\")\n",
     {
@@ -133,8 +141,9 @@
     "string",
     "bool ",
     "\n{\n",
+    "struct ",
     " readonly ",
-    "sealed ",
+    "",
     "enum ",
     ",\n",
     " { get",
@@ -146,6 +155,9 @@
     "",
     "Position",
     "Offset",
+    "__p.",
+    "Table.",
+    "?",
     "using System;\nusing FlatBuffers;\n\n",
     {
       nullptr,
@@ -162,6 +174,7 @@
     "string",
     "bool ",
     "\n{\n",
+    "class ",
     "const ",
     " ",
     "class ",
@@ -175,6 +188,9 @@
     "",
     "position()",
     "offset()",
+    "",
+    "",
+    "",
     "import (\n\tflatbuffers \"github.com/google/flatbuffers/go\"\n)",
     {
       nullptr,
@@ -237,7 +253,7 @@
   // Save out the generated code for a single class while adding
   // declaration boilerplate.
   bool SaveType(const std::string &defname, const Namespace &ns,
-  	  const std::string &classcode, bool needs_includes) {
+      const std::string &classcode, bool needs_includes) {
     if (!classcode.length()) return true;
 
     std::string code;
@@ -343,7 +359,8 @@
                                       const std::string &variable_name)
 {
   if(lang_.language == IDLOptions::kCSharp) {
-    return "new Offset<" + WrapInNameSpace(struct_def) + ">(" + variable_name + ")";
+    return "new Offset<" + WrapInNameSpace(struct_def) + ">(" + variable_name +
+           ")";
   }
   return variable_name;
 }
@@ -401,9 +418,11 @@
 }
 
 // Cast statements for mutator method parameters.
-// In Java, parameters representing unsigned numbers need to be cast down to their respective type.
-// For example, a long holding an unsigned int value would be cast down to int before being put onto the buffer.
-// In C#, one cast directly cast an Enum to its underlying type, which is essential before putting it onto the buffer.
+// In Java, parameters representing unsigned numbers need to be cast down to
+// their respective type. For example, a long holding an unsigned int value
+// would be cast down to int before being put onto the buffer. In C#, one cast
+// directly cast an Enum to its underlying type, which is essential before
+// putting it onto the buffer.
 std::string SourceCast(const Type &type, bool castFromDest) {
   if (type.base_type == BASE_TYPE_VECTOR) {
     return SourceCast(type.VectorType(), castFromDest);
@@ -484,7 +503,8 @@
         case BASE_TYPE_STRING:
           return "default(StringOffset)";
         case BASE_TYPE_STRUCT:
-          return "default(Offset<" + WrapInNameSpace(*value.type.struct_def) + ">)";
+          return "default(Offset<" + WrapInNameSpace(*value.type.struct_def) +
+                 ">)";
         case BASE_TYPE_VECTOR:
           return "default(VectorOffset)";
         default:
@@ -513,7 +533,8 @@
   GenComment(enum_def.doc_comment, code_ptr, &lang_.comment_config);
   code += std::string("public ") + lang_.enum_decl + enum_def.name;
   if (lang_.language == IDLOptions::kCSharp) {
-    code += lang_.inheritance_marker + GenTypeBasic(enum_def.underlying_type, false);
+    code += lang_.inheritance_marker +
+            GenTypeBasic(enum_def.underlying_type, false);
   }
   code += lang_.open_curly;
   if (lang_.language == IDLOptions::kJava) {
@@ -578,12 +599,13 @@
 // Returns the function name that is able to read a value of the given type.
 std::string GenGetter(const Type &type) {
   switch (type.base_type) {
-    case BASE_TYPE_STRING: return "__string";
-    case BASE_TYPE_STRUCT: return "__struct";
-    case BASE_TYPE_UNION:  return "__union";
+    case BASE_TYPE_STRING: return lang_.accessor_prefix + "__string";
+    case BASE_TYPE_STRUCT: return lang_.accessor_prefix + "__struct";
+    case BASE_TYPE_UNION:  return lang_.accessor_prefix + "__union";
     case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
     default: {
-      std::string getter = "bb." + FunctionStart('G') + "et";
+      std::string getter =
+        lang_.accessor_prefix + "bb." + FunctionStart('G') + "et";
       if (type.base_type == BASE_TYPE_BOOL) {
         getter = "0!=" + getter;
       } else if (GenTypeBasic(type, false) != "byte") {
@@ -598,7 +620,8 @@
 // Hence a setter method will only be generated for such fields.
 std::string GenSetter(const Type &type) {
   if (IsScalar(type.base_type)) {
-    std::string setter = "bb." + FunctionStart('P') + "ut";
+    std::string setter =
+      lang_.accessor_prefix + "bb." + FunctionStart('P') + "ut";
     if (GenTypeBasic(type, false) != "byte" &&
         type.base_type != BASE_TYPE_BOOL) {
       setter += MakeCamel(GenTypeBasic(type, false));
@@ -618,7 +641,8 @@
 
 // Recursively generate arguments for a constructor, to deal with nested
 // structs.
-void GenStructArgs(const StructDef &struct_def, std::string *code_ptr, const char *nameprefix) {
+void GenStructArgs(const StructDef &struct_def, std::string *code_ptr,
+                   const char *nameprefix) {
   std::string &code = *code_ptr;
   for (auto it = struct_def.fields.vec.begin();
        it != struct_def.fields.vec.end();
@@ -643,7 +667,8 @@
 // Recusively generate struct construction statements of the form:
 // builder.putType(name);
 // and insert manual padding.
-void GenStructBody(const StructDef &struct_def, std::string *code_ptr, const char *nameprefix) {
+void GenStructBody(const StructDef &struct_def, std::string *code_ptr,
+                   const char *nameprefix) {
   std::string &code = *code_ptr;
   code += "    builder." + FunctionStart('P') + "rep(";
   code += NumToString(struct_def.minalign) + ", ";
@@ -669,6 +694,90 @@
   }
 }
 
+std::string GenByteBufferLength(const char *bb_name) {
+  std::string bb_len = bb_name;
+  if (lang_.language == IDLOptions::kCSharp) bb_len += ".Length";
+  else bb_len += ".array().length";
+  return bb_len;
+}
+
+std::string GenOffsetGetter(flatbuffers::FieldDef *key_field,
+                            const char *num = nullptr) {
+  std::string key_offset = "";
+  key_offset += lang_.accessor_prefix_static + "__offset(" +
+    NumToString(key_field->value.offset) + ", ";
+  if (num) {
+    key_offset += num;
+    key_offset += (lang_.language == IDLOptions::kCSharp ?
+      ".Value, builder.DataBuffer)" : ", _bb)");
+  } else {
+    key_offset += GenByteBufferLength("bb");
+    key_offset += " - tableOffset, bb)";
+  }
+  return key_offset;
+}
+
+std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) {
+  std::string key_getter = "      ";
+  key_getter += "int tableOffset = " + lang_.accessor_prefix_static;
+  key_getter += "__indirect(vectorLocation + 4 * (start + middle)";
+  key_getter += ", bb);\n      ";
+  if (key_field->value.type.base_type == BASE_TYPE_STRING) {
+    key_getter += "int comp = " + lang_.accessor_prefix_static;
+    key_getter += FunctionStart('C') + "ompareStrings(";
+    key_getter += GenOffsetGetter(key_field);
+    key_getter += ", byteKey, bb);\n";
+  } else {
+    auto get_val = GenGetter(key_field->value.type) +
+      "(" + GenOffsetGetter(key_field) + ")";
+    if (lang_.language == IDLOptions::kCSharp) {
+      key_getter += "int comp = " + get_val + ".CompareTo(key);\n";
+    } else {
+      key_getter += GenTypeGet(key_field->value.type) + " val = ";
+      key_getter += get_val + ";\n";
+      key_getter += "      int comp = val > key ? 1 : val < key ? -1 : 0;\n";
+    }
+  }
+  return key_getter;
+}
+
+
+std::string GenKeyGetter(flatbuffers::FieldDef *key_field) {
+  std::string key_getter = "";
+  auto data_buffer = (lang_.language == IDLOptions::kCSharp) ?
+    "builder.DataBuffer" : "_bb";
+  if (key_field->value.type.base_type == BASE_TYPE_STRING) {
+    if (lang_.language == IDLOptions::kJava)
+      key_getter += " return ";
+    key_getter += lang_.accessor_prefix_static;
+    key_getter += FunctionStart('C') + "ompareStrings(";
+    key_getter += GenOffsetGetter(key_field, "o1") + ", ";
+    key_getter += GenOffsetGetter(key_field, "o2") + ", " + data_buffer + ")";
+    if (lang_.language == IDLOptions::kJava)
+      key_getter += ";";
+  }
+  else {
+    auto field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
+      "(" + GenOffsetGetter(key_field, "o1") + ")";
+    if (lang_.language == IDLOptions::kCSharp) {
+      key_getter += field_getter;
+      field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
+        "(" + GenOffsetGetter(key_field, "o2") + ")";
+      key_getter += ".CompareTo(" + field_getter + ")";
+    }
+    else {
+      key_getter += "\n    " + GenTypeGet(key_field->value.type) + " val_1 = ";
+      key_getter += field_getter + ";\n    " + GenTypeGet(key_field->value.type);
+      key_getter += " val_2 = ";
+      field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
+        "(" + GenOffsetGetter(key_field, "o2") + ")";
+      key_getter += field_getter + ";\n";
+      key_getter += "    return val_1 > val_2 ? 1 : val_1 < val_2 ? -1 : 0;\n ";
+    }
+  }
+  return key_getter;
+}
+
 void GenStruct(StructDef &struct_def, std::string *code_ptr) {
   if (struct_def.generated) return;
   std::string &code = *code_ptr;
@@ -685,18 +794,32 @@
       struct_def.attributes.Lookup("csharp_partial")) {
     // generate a partial class for this C# struct/table
     code += "partial ";
-  }
-  else {
+  } else {
     code += lang_.unsubclassable_decl;
   }
-  code += "class " + struct_def.name + lang_.inheritance_marker;
-  code += struct_def.fixed ? "Struct" : "Table";
-  code += " {\n";
+  code += lang_.accessor_type + struct_def.name;
+  if (lang_.language == IDLOptions::kCSharp) {
+    code += " : IFlatbufferObject";
+    code += lang_.open_curly;
+    code += "  private ";
+    code += struct_def.fixed ? "Struct" : "Table";
+    code += " __p;\n";
+
+    if (lang_.language == IDLOptions::kCSharp) {
+        code += "  public ByteBuffer ByteBuffer { get { return __p.bb; } }\n";
+    }
+
+  } else {
+    code += lang_.inheritance_marker;
+    code += struct_def.fixed ? "Struct" : "Table";
+    code += lang_.open_curly;
+  }
   if (!struct_def.fixed) {
     // Generate a special accessor for the table that when used as the root
     // of a FlatBuffer
     std::string method_name = FunctionStart('G') + "etRootAs" + struct_def.name;
-    std::string method_signature = "  public static " + struct_def.name + " " + method_name;
+    std::string method_signature = "  public static " + struct_def.name + " " +
+                                   method_name;
 
     // create convenience method that doesn't require an existing object
     code += method_signature + "(ByteBuffer _bb) ";
@@ -705,8 +828,7 @@
     // create method that allows object reuse
     code += method_signature + "(ByteBuffer _bb, " + struct_def.name + " obj) { ";
     code += lang_.set_bb_byteorder;
-    code += "return (obj.__init(_bb." + FunctionStart('G');
-    code += "etInt(_bb.";
+    code += "return (obj.__assign(_bb." + FunctionStart('G') + "etInt(_bb.";
     code += lang_.get_bb_position;
     code += ") + _bb.";
     code += lang_.get_bb_position;
@@ -717,16 +839,19 @@
         code += "  public static ";
         code += lang_.bool_type + struct_def.name;
         code += "BufferHasIdentifier(ByteBuffer _bb) { return ";
-        code += "__has_identifier(_bb, \"" + parser_.file_identifier_;
+        code += lang_.accessor_prefix_static + "__has_identifier(_bb, \"";
+        code += parser_.file_identifier_;
         code += "\"); }\n";
       }
     }
   }
   // Generate the __init method that sets the field in a pre-existing
   // accessor object. This is to allow object reuse.
-  code += "  public " + struct_def.name;
-  code += " __init(int _i, ByteBuffer _bb) ";
-  code += "{ bb_pos = _i; bb = _bb; return this; }\n\n";
+  code += "  public void __init(int _i, ByteBuffer _bb) ";
+  code += "{ " + lang_.accessor_prefix + "bb_pos = _i; ";
+  code += lang_.accessor_prefix + "bb = _bb; }\n";
+  code += "  public " + struct_def.name + " __assign(int _i, ByteBuffer _bb) ";
+  code += "{ __init(_i, _bb); return this; }\n\n";
   for (auto it = struct_def.fields.vec.begin();
        it != struct_def.fields.vec.end();
        ++it) {
@@ -735,28 +860,35 @@
     GenComment(field.doc_comment, code_ptr, &lang_.comment_config, "  ");
     std::string type_name = GenTypeGet(field.value.type);
     std::string type_name_dest = GenTypeNameDest(field.value.type);
+    std::string conditional_cast = "";
+    std::string optional = "";
+    if (lang_.language == IDLOptions::kCSharp &&
+        !struct_def.fixed &&
+        (field.value.type.base_type == BASE_TYPE_STRUCT ||
+         field.value.type.base_type == BASE_TYPE_UNION ||
+         (field.value.type.base_type == BASE_TYPE_VECTOR &&
+          field.value.type.element == BASE_TYPE_STRUCT))) {
+      optional = lang_.optional_suffix;
+      conditional_cast = "(" + type_name_dest + optional + ")";
+    }
     std::string dest_mask = DestinationMask(field.value.type, true);
     std::string dest_cast = DestinationCast(field.value.type);
     std::string src_cast = SourceCast(field.value.type);
-    std::string method_start = "  public " + type_name_dest + " " +
+    std::string method_start = "  public " + type_name_dest + optional + " " +
                                MakeCamel(field.name, lang_.first_camel_upper);
+    std::string obj = lang_.language == IDLOptions::kCSharp
+      ? "(new " + type_name + "())"
+      : "obj";
 
     // Most field accessors need to retrieve and test the field offset first,
     // this is the prefix code for that:
-    auto offset_prefix = " { int o = __offset(" +
-      NumToString(field.value.offset) +
-      "); return o != 0 ? ";
+    auto offset_prefix = " { int o = " + lang_.accessor_prefix + "__offset(" +
+                         NumToString(field.value.offset) +
+                         "); return o != 0 ? ";
     // Generate the accessors that don't do object reuse.
     if (field.value.type.base_type == BASE_TYPE_STRUCT) {
       // Calls the accessor that takes an accessor object with a new object.
-      if (lang_.language == IDLOptions::kCSharp) {
-        code += method_start + " { get { return Get";
-        code += MakeCamel(field.name, lang_.first_camel_upper);
-        code += "(new ";
-        code += type_name + "()); } }\n";
-        method_start = "  public " + type_name_dest + " Get" + MakeCamel(field.name, lang_.first_camel_upper);
-      }
-      else {
+      if (lang_.language != IDLOptions::kCSharp) {
         code += method_start + "() { return ";
         code += MakeCamel(field.name, lang_.first_camel_upper);
         code += "(new ";
@@ -766,24 +898,16 @@
                field.value.type.element == BASE_TYPE_STRUCT) {
       // Accessors for vectors of structs also take accessor objects, this
       // generates a variant without that argument.
-      if (lang_.language == IDLOptions::kCSharp) {
-        method_start = "  public " + type_name_dest + " Get" + MakeCamel(field.name, lang_.first_camel_upper);
-        code += method_start + "(int j) { return Get";
-      } else {
+      if (lang_.language != IDLOptions::kCSharp) {
         code += method_start + "(int j) { return ";
-      }
-      code += MakeCamel(field.name, lang_.first_camel_upper);
-      code += "(new ";
-      code += type_name + "(), j); }\n";
-    } else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
-      if (lang_.language == IDLOptions::kCSharp) {
-        method_start = "  public " + type_name_dest + " Get" + MakeCamel(field.name, lang_.first_camel_upper);
+        code += MakeCamel(field.name, lang_.first_camel_upper);
+        code += "(new " + type_name + "(), j); }\n";
       }
     } else if (field.value.type.base_type == BASE_TYPE_UNION) {
       if (lang_.language == IDLOptions::kCSharp) {
-        // union types in C# use generic Table-derived type for better type safety
-        method_start = "  public " + type_name_dest + " Get" + MakeCamel(field.name, lang_.first_camel_upper) + "<TTable>";
-        offset_prefix = " where TTable : Table" + offset_prefix;
+        // Union types in C# use generic Table-derived type for better type
+        // safety.
+        method_start += "<TTable>";
         type_name = type_name_dest;
       }
     }
@@ -793,64 +917,78 @@
     // only create default casts for c# scalars or vectors of scalars
     if (lang_.language == IDLOptions::kCSharp &&
         (IsScalar(field.value.type.base_type) ||
-         (field.value.type.base_type == BASE_TYPE_VECTOR && IsScalar(field.value.type.element)))) {
-      // For scalars, default value will be returned by GetDefaultValue(). If the scalar is an enum, GetDefaultValue()
-      // returns an actual c# enum that doesn't need to be casted. However, default values for enum elements of
-      // vectors are integer literals ("0") and are still casted for clarity.
-      if (field.value.type.enum_def == nullptr || field.value.type.base_type == BASE_TYPE_VECTOR) {
+         (field.value.type.base_type == BASE_TYPE_VECTOR &&
+          IsScalar(field.value.type.element)))) {
+      // For scalars, default value will be returned by GetDefaultValue().
+      // If the scalar is an enum, GetDefaultValue() returns an actual c# enum
+      // that doesn't need to be casted. However, default values for enum
+      // elements of vectors are integer literals ("0") and are still casted
+      // for clarity.
+      if (field.value.type.enum_def == nullptr ||
+          field.value.type.base_type == BASE_TYPE_VECTOR) {
           default_cast = "(" + type_name_dest + ")";
       }
     }
-    std::string member_suffix = "";
+    std::string member_suffix = "; ";
     if (IsScalar(field.value.type.base_type)) {
       code += lang_.getter_prefix;
-      member_suffix = lang_.getter_suffix;
+      member_suffix += lang_.getter_suffix;
       if (struct_def.fixed) {
         code += " { return " + getter;
-        code += "(bb_pos + " + NumToString(field.value.offset) + ")";
+        code += "(" + lang_.accessor_prefix + "bb_pos + ";
+        code += NumToString(field.value.offset) + ")";
         code += dest_mask;
       } else {
         code += offset_prefix + getter;
-        code += "(o + bb_pos)" + dest_mask + " : " + default_cast;
+        code += "(o + " + lang_.accessor_prefix + "bb_pos)" + dest_mask;
+        code += " : " + default_cast;
         code += GenDefaultValue(field.value);
       }
     } else {
       switch (field.value.type.base_type) {
         case BASE_TYPE_STRUCT:
-          code += "(" + type_name + " obj";
-          if (struct_def.fixed) {
-            code += ") { return obj.__init(bb_pos + ";
-            code += NumToString(field.value.offset) + ", bb)";
+          if (lang_.language != IDLOptions::kCSharp) {
+            code += "(" + type_name + " obj" + ")";
           } else {
-            code += ")";
-            code += offset_prefix;
-            code += "obj.__init(";
+            code += lang_.getter_prefix;
+            member_suffix += lang_.getter_suffix;
+          }
+          if (struct_def.fixed) {
+            code += " { return " + obj + ".__assign(" + lang_.accessor_prefix;
+            code += "bb_pos + " + NumToString(field.value.offset) + ", ";
+            code += lang_.accessor_prefix + "bb)";
+          } else {
+            code += offset_prefix + conditional_cast;
+            code += obj + ".__assign(";
             code += field.value.type.struct_def->fixed
-                      ? "o + bb_pos"
-                      : "__indirect(o + bb_pos)";
-            code += ", bb) : null";
+                      ? "o + " + lang_.accessor_prefix + "bb_pos"
+                      : lang_.accessor_prefix + "__indirect(o + " +
+                        lang_.accessor_prefix + "bb_pos)";
+            code += ", " + lang_.accessor_prefix + "bb) : null";
           }
           break;
         case BASE_TYPE_STRING:
           code += lang_.getter_prefix;
-          member_suffix = lang_.getter_suffix;
-          code += offset_prefix + getter + "(o + bb_pos) : null";
+          member_suffix += lang_.getter_suffix;
+          code += offset_prefix + getter + "(o + " + lang_.accessor_prefix;
+          code += "bb_pos) : null";
           break;
         case BASE_TYPE_VECTOR: {
           auto vectortype = field.value.type.VectorType();
           code += "(";
           if (vectortype.base_type == BASE_TYPE_STRUCT) {
-            code += type_name + " obj, ";
-            getter = "obj.__init";
+            if (lang_.language != IDLOptions::kCSharp)
+              code += type_name + " obj, ";
+            getter = obj + ".__assign";
           }
-          code += "int j)" + offset_prefix + getter +"(";
-          auto index = "__vector(o) + j * " +
+          code += "int j)" + offset_prefix + conditional_cast + getter +"(";
+          auto index = lang_.accessor_prefix + "__vector(o) + j * " +
                        NumToString(InlineSize(vectortype));
           if (vectortype.base_type == BASE_TYPE_STRUCT) {
             code += vectortype.struct_def->fixed
                       ? index
-                      : "__indirect(" + index + ")";
-            code += ", bb";
+                      : lang_.accessor_prefix + "__indirect(" + index + ")";
+            code += ", " + lang_.accessor_prefix + "bb";
           } else {
             code += index;
           }
@@ -861,14 +999,19 @@
           break;
         }
         case BASE_TYPE_UNION:
-          code += "(" + type_name + " obj)" + offset_prefix + getter;
-          code += "(obj, o) : null";
+          if (lang_.language == IDLOptions::kCSharp) {
+            code += "() where TTable : struct, IFlatbufferObject";
+            code += offset_prefix + "(TTable?)" + getter;
+            code += "<TTable>(o) : null";
+          } else {
+            code += "(" + type_name + " obj)" + offset_prefix + getter;
+            code += "(obj, o) : null";
+          }
           break;
         default:
           assert(0);
       }
     }
-    code += "; ";
     code += member_suffix;
     code += "}\n";
     if (field.value.type.base_type == BASE_TYPE_VECTOR) {
@@ -876,7 +1019,7 @@
       code += "Length";
       code += lang_.getter_prefix;
       code += offset_prefix;
-      code += "__vector_len(o) : 0; ";
+      code += lang_.accessor_prefix + "__vector_len(o) : 0; ";
       code += lang_.getter_suffix;
       code += "}\n";
     }
@@ -888,16 +1031,19 @@
         case IDLOptions::kJava:
           code += "  public ByteBuffer ";
           code += MakeCamel(field.name, lang_.first_camel_upper);
-          code += "AsByteBuffer() { return __vector_as_bytebuffer(";
+          code += "AsByteBuffer() { return ";
+          code += lang_.accessor_prefix + "__vector_as_bytebuffer(";
           code += NumToString(field.value.offset) + ", ";
-          code += NumToString(field.value.type.base_type == BASE_TYPE_STRING ? 1 :
-                              InlineSize(field.value.type.VectorType()));
+          code += NumToString(field.value.type.base_type == BASE_TYPE_STRING
+                              ? 1
+                              : InlineSize(field.value.type.VectorType()));
           code += "); }\n";
           break;
         case IDLOptions::kCSharp:
           code += "  public ArraySegment<byte>? Get";
           code += MakeCamel(field.name, lang_.first_camel_upper);
-          code += "Bytes() { return __vector_as_arraysegment(";
+          code += "Bytes() { return ";
+          code += lang_.accessor_prefix + "__vector_as_arraysegment(";
           code += NumToString(field.value.offset);
           code += "); }\n";
           break;
@@ -917,30 +1063,49 @@
     auto getNestedMethodName = nestedMethodName;
     if (lang_.language == IDLOptions::kCSharp) {
       getNestedMethodName = "Get" + nestedMethodName;
+      conditional_cast = "(" + nested_type_name + lang_.optional_suffix + ")";
     }
-    code += "  public " + nested_type_name + " ";
-    code += nestedMethodName + "() { return ";
-    code += getNestedMethodName + "(new " + nested_type_name + "()); }\n";
-    code += "  public " + nested_type_name + " " + getNestedMethodName;
-    code += "(" + nested_type_name + " obj) { ";
-    code += "int o = __offset(" + NumToString(field.value.offset) +"); ";
-    code += "return o != 0 ? obj.__init(__indirect(__vector(o)), bb) : null; }\n";
+    if (lang_.language != IDLOptions::kCSharp) {
+      code += "  public " + nested_type_name + lang_.optional_suffix + " ";
+      code += nestedMethodName + "() { return ";
+      code += getNestedMethodName + "(new " + nested_type_name + "()); }\n";
+    } else {
+      obj = "(new " + nested_type_name + "())";
+    }
+    code += "  public " + nested_type_name + lang_.optional_suffix + " ";
+    code += getNestedMethodName + "(";
+    if (lang_.language != IDLOptions::kCSharp)
+      code += nested_type_name + " obj";
+    code += ") { int o = " + lang_.accessor_prefix + "__offset(";
+    code += NumToString(field.value.offset) +"); ";
+    code += "return o != 0 ? " + conditional_cast + obj + ".__assign(";
+    code += lang_.accessor_prefix;
+    code += "__indirect(" + lang_.accessor_prefix + "__vector(o)), ";
+    code += lang_.accessor_prefix + "bb) : null; }\n";
   }
-    // generate mutators for scalar fields or vectors of scalars
+    // Generate mutators for scalar fields or vectors of scalars.
     if (parser_.opts.mutable_buffer) {
       auto underlying_type = field.value.type.base_type == BASE_TYPE_VECTOR
                     ? field.value.type.VectorType()
                     : field.value.type;
-      // boolean parameters have to be explicitly converted to byte representation
-      auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL ? "(byte)(" + field.name + " ? 1 : 0)" : field.name;
+      // Boolean parameters have to be explicitly converted to byte
+      // representation.
+      auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL
+        ? "(byte)(" + field.name + " ? 1 : 0)"
+        : field.name;
       auto mutator_prefix = MakeCamel("mutate", lang_.first_camel_upper);
-      //a vector mutator also needs the index of the vector element it should mutate
-      auto mutator_params = (field.value.type.base_type == BASE_TYPE_VECTOR ? "(int j, " : "(") +
-                            GenTypeNameDest(underlying_type) + " " +
-                            field.name + ") { ";
+      // A vector mutator also needs the index of the vector element it should
+      // mutate.
+      auto mutator_params = (field.value.type.base_type == BASE_TYPE_VECTOR
+        ? "(int j, "
+        : "(") + GenTypeNameDest(underlying_type) + " " + field.name + ") { ";
       auto setter_index = field.value.type.base_type == BASE_TYPE_VECTOR
-                    ? "__vector(o) + j * " + NumToString(InlineSize(underlying_type))
-                    : (struct_def.fixed ? "bb_pos + " + NumToString(field.value.offset) : "o + bb_pos");
+        ? lang_.accessor_prefix + "__vector(o) + j * " +
+          NumToString(InlineSize(underlying_type))
+        : (struct_def.fixed
+            ? lang_.accessor_prefix + "bb_pos + " +
+              NumToString(field.value.offset)
+            : "o + " + lang_.accessor_prefix + "bb_pos");
       if (IsScalar(field.value.type.base_type) ||
           (field.value.type.base_type == BASE_TYPE_VECTOR &&
           IsScalar(field.value.type.VectorType().base_type))) {
@@ -952,14 +1117,17 @@
           code += GenSetter(underlying_type) + "(" + setter_index + ", ";
           code += src_cast + setter_parameter + "); }\n";
         } else {
-          code += "int o = __offset(" + NumToString(field.value.offset) + ");";
+          code += "int o = " + lang_.accessor_prefix + "__offset(";
+          code += NumToString(field.value.offset) + ");";
           code += " if (o != 0) { " + GenSetter(underlying_type);
-          code += "(" + setter_index + ", " + src_cast + setter_parameter + "); return true; } else { return false; } }\n";
+          code += "(" + setter_index + ", " + src_cast + setter_parameter +
+                  "); return true; } else { return false; } }\n";
         }
       }
     }
   }
   code += "\n";
+  flatbuffers::FieldDef *key_field = nullptr;
   if (struct_def.fixed) {
     // create a struct constructor function
     code += "  public static " + GenOffsetType(struct_def) + " ";
@@ -969,7 +1137,8 @@
     code += ") {\n";
     GenStructBody(struct_def, code_ptr, "");
     code += "    return ";
-    code += GenOffsetConstruct(struct_def, "builder." + std::string(lang_.get_fbb_offset));
+    code += GenOffsetConstruct(struct_def,
+                               "builder." + std::string(lang_.get_fbb_offset));
     code += ";\n  }\n";
   } else {
     // Generate a method that creates a table in one go. This is only possible
@@ -1048,6 +1217,7 @@
          it != struct_def.fields.vec.end(); ++it) {
       auto &field = **it;
       if (field.deprecated) continue;
+      if (field.key) key_field = &field;
       code += "  public static void " + FunctionStart('A') + "dd";
       code += MakeCamel(field.name);
       code += "(FlatBufferBuilder builder, ";
@@ -1059,7 +1229,9 @@
       code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
       code += SourceCastBasic(field.value.type);
       code += argname;
-      if(!IsScalar(field.value.type.base_type) && field.value.type.base_type != BASE_TYPE_UNION && lang_.language == IDLOptions::kCSharp) {
+      if (!IsScalar(field.value.type.base_type) &&
+          field.value.type.base_type != BASE_TYPE_UNION &&
+          lang_.language == IDLOptions::kCSharp) {
         code += ".Value";
       }
       code += ", " + GenDefaultValue(field.value, false);
@@ -1070,7 +1242,8 @@
         auto elem_size = InlineSize(vector_type);
         if (!IsStruct(vector_type)) {
           // Generate a method to create a vector from a Java array.
-          code += "  public static " + GenVectorOffsetType() + " " + FunctionStart('C') + "reate";
+          code += "  public static " + GenVectorOffsetType() + " ";
+          code += FunctionStart('C') + "reate";
           code += MakeCamel(field.name);
           code += "Vector(FlatBufferBuilder builder, ";
           code += GenTypeBasic(vector_type) + "[] data) ";
@@ -1086,7 +1259,8 @@
           code += SourceCastBasic(vector_type, false);
           code += "data[i]";
           if (lang_.language == IDLOptions::kCSharp &&
-            (vector_type.base_type == BASE_TYPE_STRUCT || vector_type.base_type == BASE_TYPE_STRING))
+              (vector_type.base_type == BASE_TYPE_STRUCT ||
+               vector_type.base_type == BASE_TYPE_STRING))
             code += ".Value";
           code += "); return ";
           code += "builder." + FunctionStart('E') + "ndVector(); }\n";
@@ -1119,7 +1293,8 @@
     if (parser_.root_struct_def_ == &struct_def) {
       code += "  public static void ";
       code += FunctionStart('F') + "inish" + struct_def.name;
-      code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType(struct_def) + " offset) {";
+      code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType(struct_def);
+      code += " offset) {";
       code += " builder." + FunctionStart('F') + "inish(offset";
       if (lang_.language == IDLOptions::kCSharp) {
         code += ".Value";
@@ -1130,6 +1305,58 @@
       code += "); }\n";
     }
   }
+  if (struct_def.has_key) {
+    if (lang_.language == IDLOptions::kJava) {
+      code += "\n  @Override\n  protected int keysCompare(";
+      code += "Integer o1, Integer o2, ByteBuffer _bb) {";
+      code += GenKeyGetter(key_field);
+      code += " }\n";
+    }
+    else {
+      code += "\n  public static VectorOffset ";
+      code += "CreateMySortedVectorOfTables(FlatBufferBuilder builder, ";
+      code += "Offset<" + struct_def.name + ">";
+      code += "[] offsets) {\n";
+      code += "    Array.Sort(offsets, (Offset<" + struct_def.name +
+        "> o1, Offset<" + struct_def.name + "> o2) => " + GenKeyGetter(key_field);
+      code += ");\n";
+      code += "    return builder.CreateVectorOfTables(offsets);\n  }\n";
+    }
+
+    code += "\n  public static " + struct_def.name + lang_.optional_suffix;
+    code += " " + FunctionStart('L') + "ookupByKey(" + GenVectorOffsetType();
+    code += " vectorOffset, " + GenTypeGet(key_field->value.type);
+    code += " key, ByteBuffer bb) {\n";
+    if (key_field->value.type.base_type == BASE_TYPE_STRING) {
+      code += "    byte[] byteKey = ";
+      if (lang_.language == IDLOptions::kJava)
+        code += "key.getBytes(Table.UTF8_CHARSET.get());\n";
+      else
+        code += "System.Text.Encoding.UTF8.GetBytes(key);\n";
+    }
+    code += "    int vectorLocation = " + GenByteBufferLength("bb");
+    code += " - vectorOffset";
+    if (lang_.language == IDLOptions::kCSharp) code += ".Value";
+    code += ";\n    int span = ";
+    code += "bb." + FunctionStart('G') + "etInt(vectorLocation);\n";
+    code += "    int start = 0;\n";
+    code += "    vectorLocation += 4;\n";
+    code += "    while (span != 0) {\n";
+    code += "      int middle = span / 2;\n";
+    code += GenLookupKeyGetter(key_field);
+    code += "      if (comp > 0) {\n";
+    code += "        span = middle;\n";
+    code += "      } else if (comp < 0) {\n";
+    code += "        middle++;\n";
+    code += "        start += middle;\n";
+    code += "        span -= middle;\n";
+    code += "      } else {\n";
+    code += "        return new " + struct_def.name;
+    code += "().__assign(tableOffset, bb);\n";
+    code += "      }\n    }\n";
+    code += "    return null;\n";
+    code += "  }\n";
+  }
   code += "}";
   // Java does not need the closing semi-colon on class definitions.
   code += (lang_.language != IDLOptions::kJava) ? ";" : "";
diff --git a/src/idl_gen_grpc.cpp b/src/idl_gen_grpc.cpp
index 6ada3e8..9bcd5bc 100644
--- a/src/idl_gen_grpc.cpp
+++ b/src/idl_gen_grpc.cpp
@@ -24,7 +24,7 @@
 
 namespace flatbuffers {
 
-class FlatBufMethod : public grpc_cpp_generator::Method {
+class FlatBufMethod : public grpc_generator::Method {
  public:
   enum Streaming { kNone, kClient, kServer, kBiDi };
 
@@ -62,7 +62,7 @@
   Streaming streaming_;
 };
 
-class FlatBufService : public grpc_cpp_generator::Service {
+class FlatBufService : public grpc_generator::Service {
  public:
   FlatBufService(const ServiceDef *service) : service_(service) {}
 
@@ -72,8 +72,8 @@
     return static_cast<int>(service_->calls.vec.size());
   };
 
-  std::unique_ptr<const grpc_cpp_generator::Method> method(int i) const {
-    return std::unique_ptr<const grpc_cpp_generator::Method>(
+  std::unique_ptr<const grpc_generator::Method> method(int i) const {
+    return std::unique_ptr<const grpc_generator::Method>(
           new FlatBufMethod(service_->calls.vec[i]));
   };
 
@@ -81,7 +81,7 @@
   const ServiceDef *service_;
 };
 
-class FlatBufPrinter : public grpc_cpp_generator::Printer {
+class FlatBufPrinter : public grpc_generator::Printer {
  public:
   FlatBufPrinter(std::string *str)
     : str_(str), escape_char_('$'), indent_(0) {}
@@ -133,7 +133,7 @@
   int indent_;
 };
 
-class FlatBufFile : public grpc_cpp_generator::File {
+class FlatBufFile : public grpc_generator::File {
  public:
   FlatBufFile(const Parser &parser, const std::string &file_name)
     : parser_(parser), file_name_(file_name) {}
@@ -163,13 +163,13 @@
     return static_cast<int>(parser_.services_.vec.size());
   };
 
-  std::unique_ptr<const grpc_cpp_generator::Service> service(int i) const {
-    return std::unique_ptr<const grpc_cpp_generator::Service> (
+  std::unique_ptr<const grpc_generator::Service> service(int i) const {
+    return std::unique_ptr<const grpc_generator::Service> (
           new FlatBufService(parser_.services_.vec[i]));
   }
 
-  std::unique_ptr<grpc_cpp_generator::Printer> CreatePrinter(std::string *str) const {
-    return std::unique_ptr<grpc_cpp_generator::Printer>(
+  std::unique_ptr<grpc_generator::Printer> CreatePrinter(std::string *str) const {
+    return std::unique_ptr<grpc_generator::Printer>(
           new FlatBufPrinter(str));
   }
 
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index 6a5808d..dc3604d 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -219,7 +219,7 @@
       return Error("escape code must be followed by " + NumToString(nibbles) +
                    " hex digits");
   std::string target(cursor_, cursor_ + nibbles);
-  *val = StringToUInt(target.c_str(), 16);
+  *val = StringToUInt(target.c_str(), nullptr, 16);
   cursor_ += nibbles;
   return NoError();
 }
@@ -447,7 +447,7 @@
               cursor_++;
               while (isxdigit(static_cast<unsigned char>(*cursor_))) cursor_++;
               attribute_.append(start + 2, cursor_);
-              attribute_ = NumToString(StringToUInt(attribute_.c_str(), 16));
+              attribute_ = NumToString(StringToUInt(attribute_.c_str(), nullptr, 16));
               token_ = kTokenIntegerConstant;
               return NoError();
           }
@@ -1093,10 +1093,15 @@
       NEXT();
     } else {  // Numeric constant in string.
       if (IsInteger(e.type.base_type)) {
-        // TODO(wvo): do we want to check for garbage after the number?
-        e.constant = NumToString(StringToInt(attribute_.c_str()));
+        char *end;
+        e.constant = NumToString(StringToInt(attribute_.c_str(), &end));
+        if (*end)
+          return Error("invalid integer: " + attribute_);
       } else if (IsFloat(e.type.base_type)) {
-        e.constant = NumToString(strtod(attribute_.c_str(), nullptr));
+        char *end;
+        e.constant = NumToString(strtod(attribute_.c_str(), &end));
+        if (*end)
+          return Error("invalid float: " + attribute_);
       } else {
         assert(0);  // Shouldn't happen, we covered all types.
         e.constant = "0";
diff --git a/tests/FlatBuffers.Test/ByteBufferTests.cs b/tests/FlatBuffers.Test/ByteBufferTests.cs
index b86c365..3324f12 100644
--- a/tests/FlatBuffers.Test/ByteBufferTests.cs
+++ b/tests/FlatBuffers.Test/ByteBufferTests.cs
@@ -40,6 +40,7 @@
             Assert.AreEqual((byte)99, buffer[0]);
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutByteCannotPutAtOffsetPastLength()
         {
@@ -47,6 +48,7 @@
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutByte(1, 99));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutShortPopulatesBufferCorrectly()
@@ -60,6 +62,7 @@
             Assert.AreEqual((byte)0, buffer[1]);
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutShortCannotPutAtOffsetPastLength()
         {
@@ -67,7 +70,9 @@
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(2, 99));
         }
+#endif
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutShortChecksLength()
         {
@@ -83,6 +88,7 @@
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(1, 99));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutIntPopulatesBufferCorrectly()
@@ -98,6 +104,7 @@
             Assert.AreEqual(0x0A, buffer[3]);
         }
 
+ #if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutIntCannotPutAtOffsetPastLength()
         {
@@ -121,6 +128,7 @@
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutInt(2, 0x0A0B0C0D));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutLongPopulatesBufferCorrectly()
@@ -140,6 +148,7 @@
             Assert.AreEqual(0x01, buffer[7]);
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutLongCannotPutAtOffsetPastLength()
         {
@@ -163,6 +172,7 @@
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutLong(2, 0x010203040A0B0C0D));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetByteReturnsCorrectData()
@@ -173,6 +183,7 @@
             Assert.AreEqual((byte)99, uut.Get(0));
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetByteChecksOffset()
         {
@@ -180,6 +191,7 @@
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(()=>uut.Get(1));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetShortReturnsCorrectData()
@@ -191,6 +203,7 @@
             Assert.AreEqual(1, uut.GetShort(0));
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetShortChecksOffset()
         {
@@ -206,6 +219,7 @@
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetShort(1));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetIntReturnsCorrectData()
@@ -219,6 +233,7 @@
             Assert.AreEqual(0x0A0B0C0D, uut.GetInt(0));
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetIntChecksOffset()
         {
@@ -234,6 +249,7 @@
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetInt(0));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetLongReturnsCorrectData()
@@ -251,6 +267,7 @@
             Assert.AreEqual(0x010203040A0B0C0D, uut.GetLong(0));
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetLongChecksOffset()
         {
@@ -266,6 +283,7 @@
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetLong(0));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_ReverseBytesUshort()
diff --git a/tests/FlatBuffers.Test/FlatBuffers.Test.csproj b/tests/FlatBuffers.Test/FlatBuffers.Test.csproj
index cc7c5cf..6e76b07 100644
--- a/tests/FlatBuffers.Test/FlatBuffers.Test.csproj
+++ b/tests/FlatBuffers.Test/FlatBuffers.Test.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -41,6 +41,9 @@
     <Compile Include="..\..\net\FlatBuffers\ByteBuffer.cs">
       <Link>FlatBuffers\ByteBuffer.cs</Link>
     </Compile>
+    <Compile Include="..\..\net\FlatBuffers\IFlatbufferObject.cs">
+      <Link>FlatBuffers\IFlatbufferObject.cs</Link>
+    </Compile>
     <Compile Include="..\..\net\FlatBuffers\Offset.cs">
       <Link>FlatBuffers\Offset.cs</Link>
     </Compile>
@@ -116,4 +119,4 @@
   <Target Name="AfterBuild">
   </Target>
   -->
-</Project>
\ No newline at end of file
+</Project>
diff --git a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
index 80791dd..d032d7e 100644
--- a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
+++ b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
@@ -39,6 +39,19 @@
             // better for performance.
             var fbb = new FlatBufferBuilder(1);
 
+            StringOffset[] names = { fbb.CreateString("Frodo"), fbb.CreateString("Barney"), fbb.CreateString("Wilma") };
+            Offset<Monster>[] off = new Offset<Monster>[3];
+            Monster.StartMonster(fbb);
+            Monster.AddName(fbb, names[0]);
+            off[0] = Monster.EndMonster(fbb);
+            Monster.StartMonster(fbb);
+            Monster.AddName(fbb, names[1]);
+            off[1] = Monster.EndMonster(fbb);
+            Monster.StartMonster(fbb);
+            Monster.AddName(fbb, names[2]);
+            off[2] = Monster.EndMonster(fbb);
+            var sortMons = Monster.CreateMySortedVectorOfTables(fbb, off);
+
             // We set up the same values as monsterdata.json:
 
             var str = fbb.CreateString("MyMonster");
@@ -79,6 +92,7 @@
             Monster.AddTest4(fbb, test4);
             Monster.AddTestarrayofstring(fbb, testArrayOfString);
             Monster.AddTestbool(fbb, false);
+            Monster.AddTestarrayoftables(fbb, sortMons);
             var mon = Monster.EndMonster(fbb);
 
             Monster.FinishMonsterBuffer(fbb, mon);
@@ -103,6 +117,16 @@
             Assert.AreEqual(monster.MutateMana((short)10), false);
             Assert.AreEqual(monster.Mana, (short)150);
 
+            // Accessing a vector of sorted by the key tables
+            Assert.AreEqual(monster.Testarrayoftables(0).Value.Name, "Barney");
+            Assert.AreEqual(monster.Testarrayoftables(1).Value.Name, "Frodo");
+            Assert.AreEqual(monster.Testarrayoftables(2).Value.Name, "Wilma");
+
+            // Example of searching for a table by the key
+            Assert.IsTrue(Monster.LookupByKey(sortMons, "Frodo", fbb.DataBuffer) != null);
+            Assert.IsTrue(Monster.LookupByKey(sortMons, "Barney", fbb.DataBuffer) != null);
+            Assert.IsTrue(Monster.LookupByKey(sortMons, "Wilma", fbb.DataBuffer)!= null);
+
             // testType is an existing field and mutating it should succeed
             Assert.AreEqual(monster.TestType, Any.Monster);
             Assert.AreEqual(monster.MutateTestType(Any.NONE), true);
@@ -119,7 +143,7 @@
 
             for (int i = 0; i < monster.InventoryLength; i++)
             {
-                Assert.AreEqual(monster.GetInventory(i), i + 1);
+                Assert.AreEqual(monster.Inventory(i), i + 1);
             }
 
             //reverse mutation
@@ -130,7 +154,7 @@
             Assert.AreEqual(monster.MutateInventory(4, 4), true);
 
             // get a struct field and edit one of its fields
-            Vec3 pos = monster.Pos;
+            Vec3 pos = (Vec3)monster.Pos;
             Assert.AreEqual(pos.X, 1.0f);
             pos.MutateX(55.0f);
             Assert.AreEqual(pos.X, 55.0f);
@@ -148,21 +172,20 @@
             Assert.AreEqual(150, monster.Mana);
             Assert.AreEqual("MyMonster", monster.Name);
 
-            var pos = monster.Pos;
+            var pos = monster.Pos.Value;
             Assert.AreEqual(1.0f, pos.X);
             Assert.AreEqual(2.0f, pos.Y);
             Assert.AreEqual(3.0f, pos.Z);
 
             Assert.AreEqual(3.0f, pos.Test1);
             Assert.AreEqual(Color.Green, pos.Test2);
-            var t = pos.Test3;
+            var t = (MyGame.Example.Test)pos.Test3;
             Assert.AreEqual((short)5, t.A);
             Assert.AreEqual((sbyte)6, t.B);
 
             Assert.AreEqual(Any.Monster, monster.TestType);
 
-            var monster2 = new Monster();
-            Assert.IsTrue(monster.GetTest(monster2) != null);
+            var monster2 = monster.Test<Monster>().Value;
             Assert.AreEqual("Fred", monster2.Name);
 
 
@@ -170,19 +193,19 @@
             var invsum = 0;
             for (var i = 0; i < monster.InventoryLength; i++)
             {
-                invsum += monster.GetInventory(i);
+                invsum += monster.Inventory(i);
             }
             Assert.AreEqual(10, invsum);
 
-            var test0 = monster.GetTest4(0);
-            var test1 = monster.GetTest4(1);
+            var test0 = monster.Test4(0).Value;
+            var test1 = monster.Test4(1).Value;
             Assert.AreEqual(2, monster.Test4Length);
 
             Assert.AreEqual(100, test0.A + test0.B + test1.A + test1.B);
 
             Assert.AreEqual(2, monster.TestarrayofstringLength);
-            Assert.AreEqual("test1", monster.GetTestarrayofstring(0));
-            Assert.AreEqual("test2", monster.GetTestarrayofstring(1));
+            Assert.AreEqual("test1", monster.Testarrayofstring(0));
+            Assert.AreEqual("test2", monster.Testarrayofstring(1));
 
             Assert.AreEqual(false, monster.Testbool);
 
@@ -245,10 +268,10 @@
             Monster.AddTestnestedflatbuffer(fbb2, nestedBuffer);
             var monster = Monster.EndMonster(fbb2);
             Monster.FinishMonsterBuffer(fbb2, monster);
-            
+
             // Now test the data extracted from the nested buffer
             var mons = Monster.GetRootAsMonster(fbb2.DataBuffer);
-            var nestedMonster = mons.TestnestedflatbufferAsMonster();
+            var nestedMonster = mons.GetTestnestedflatbufferAsMonster().Value;
 
             Assert.AreEqual(nestedMonsterMana, nestedMonster.Mana);
             Assert.AreEqual(nestedMonsterHp, nestedMonster.Hp);
diff --git a/tests/FlatBuffers.Test/TestTable.cs b/tests/FlatBuffers.Test/TestTable.cs
index c51237b..2b506b6 100644
--- a/tests/FlatBuffers.Test/TestTable.cs
+++ b/tests/FlatBuffers.Test/TestTable.cs
@@ -19,133 +19,135 @@
     /// <summary>
     /// A test Table object that gives easy access to the slot data
     /// </summary>
-    internal class TestTable : Table
+    internal struct TestTable
     {
+        Table t;
+
         public TestTable(ByteBuffer bb, int pos)
         {
-            base.bb = bb;
-            base.bb_pos = pos;
+            t.bb = bb;
+            t.bb_pos = pos;
         }
 
         public bool GetSlot(int slot, bool def)
         {
-            var off = base.__offset(slot);
+            var off = t.__offset(slot);
 
             if (off == 0)
             {
                 return def;
             }
-            return bb.GetSbyte(bb_pos + off) != 0;
+            return t.bb.GetSbyte(t.bb_pos + off) != 0;
         }
 
         public sbyte GetSlot(int slot, sbyte def)
         {
-            var off = base.__offset(slot);
+            var off = t.__offset(slot);
 
             if (off == 0)
             {
                 return def;
             }
-            return bb.GetSbyte(bb_pos + off);
+            return t.bb.GetSbyte(t.bb_pos + off);
         }
 
         public byte GetSlot(int slot, byte def)
         {
-            var off = base.__offset(slot);
+            var off = t.__offset(slot);
 
             if (off == 0)
             {
                 return def;
             }
-            return bb.Get(bb_pos + off);
+            return t.bb.Get(t.bb_pos + off);
         }
 
         public short GetSlot(int slot, short def)
         {
-            var off = base.__offset(slot);
+            var off = t.__offset(slot);
 
             if (off == 0)
             {
                 return def;
             }
-            return bb.GetShort(bb_pos + off);
+            return t.bb.GetShort(t.bb_pos + off);
         }
 
         public ushort GetSlot(int slot, ushort def)
         {
-            var off = base.__offset(slot);
+            var off = t.__offset(slot);
 
             if (off == 0)
             {
                 return def;
             }
-            return bb.GetUshort(bb_pos + off);
+            return t.bb.GetUshort(t.bb_pos + off);
         }
 
         public int GetSlot(int slot, int def)
         {
-            var off = base.__offset(slot);
+            var off = t.__offset(slot);
 
             if (off == 0)
             {
                 return def;
             }
-            return bb.GetInt(bb_pos + off);
+            return t.bb.GetInt(t.bb_pos + off);
         }
 
         public uint GetSlot(int slot, uint def)
         {
-            var off = base.__offset(slot);
+            var off = t.__offset(slot);
 
             if (off == 0)
             {
                 return def;
             }
-            return bb.GetUint(bb_pos + off);
+            return t.bb.GetUint(t.bb_pos + off);
         }
 
         public long GetSlot(int slot, long def)
         {
-            var off = base.__offset(slot);
+            var off = t.__offset(slot);
 
             if (off == 0)
             {
                 return def;
             }
-            return bb.GetLong(bb_pos + off);
+            return t.bb.GetLong(t.bb_pos + off);
         }
 
         public ulong GetSlot(int slot, ulong def)
         {
-            var off = base.__offset(slot);
+            var off = t.__offset(slot);
 
             if (off == 0)
             {
                 return def;
             }
-            return bb.GetUlong(bb_pos + off);
+            return t.bb.GetUlong(t.bb_pos + off);
         }
 
         public float GetSlot(int slot, float def)
         {
-            var off = base.__offset(slot);
+            var off = t.__offset(slot);
 
             if (off == 0)
             {
                 return def;
             }
-            return bb.GetFloat(bb_pos + off);
+            return t.bb.GetFloat(t.bb_pos + off);
         }
 
         public double GetSlot(int slot, double def)
         {
-            var off = base.__offset(slot);
+            var off = t.__offset(slot);
 
             if (off == 0)
             {
                 return def;
             }
-            return bb.GetDouble(bb_pos + off);
+            return t.bb.GetDouble(t.bb_pos + off);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/JavaTest.java b/tests/JavaTest.java
index c0d7d03..d53e973 100755
--- a/tests/JavaTest.java
+++ b/tests/JavaTest.java
@@ -51,6 +51,19 @@
         // better for performance.
         FlatBufferBuilder fbb = new FlatBufferBuilder(1);
 
+        int[] names = {fbb.createString("Frodo"), fbb.createString("Barney"), fbb.createString("Wilma")};
+        int[] off = new int[3];
+        Monster.startMonster(fbb);
+        Monster.addName(fbb, names[0]);
+        off[0] = Monster.endMonster(fbb);
+        Monster.startMonster(fbb);
+        Monster.addName(fbb, names[1]);
+        off[1] = Monster.endMonster(fbb);
+        Monster.startMonster(fbb);
+        Monster.addName(fbb, names[2]);
+        off[2] = Monster.endMonster(fbb);
+        int sortMons = fbb.createSortedVectorOfTables(new Monster(), off);
+		
         // We set up the same values as monsterdata.json:
 
         int str = fbb.createString("MyMonster");
@@ -84,6 +97,7 @@
         Monster.addTestarrayofstring(fbb, testArrayOfString);
         Monster.addTestbool(fbb, false);
         Monster.addTesthashu32Fnv1(fbb, Integer.MAX_VALUE + 1L);
+        Monster.addTestarrayoftables(fbb, sortMons);
         int mon = Monster.endMonster(fbb);
 
         Monster.finishMonsterBuffer(fbb, mon);
@@ -121,6 +135,16 @@
         // the mana field should retain its default value
         TestEq(monster.mutateMana((short)10), false);
         TestEq(monster.mana(), (short)150);
+		
+		// Accessing a vector of sorted by the key tables
+        TestEq(monster.testarrayoftables(0).name(), "Barney");
+        TestEq(monster.testarrayoftables(1).name(), "Frodo");
+        TestEq(monster.testarrayoftables(2).name(), "Wilma");
+		
+		// Example of searching for a table by the key
+        TestEq(Monster.lookupByKey(sortMons, "Frodo", fbb.dataBuffer()).name(), "Frodo");
+        TestEq(Monster.lookupByKey(sortMons, "Barney", fbb.dataBuffer()).name(), "Barney");
+        TestEq(Monster.lookupByKey(sortMons, "Wilma", fbb.dataBuffer()).name(), "Wilma");
 
         // testType is an existing field and mutating it should succeed
         TestEq(monster.testType(), (byte)Any.Monster);
diff --git a/tests/JavaTest.sh b/tests/JavaTest.sh
index 344bd1c..40e854b 100755
--- a/tests/JavaTest.sh
+++ b/tests/JavaTest.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # Copyright 2014 Google Inc. All rights reserved.
 #
@@ -16,14 +16,29 @@
 
 echo Compile then run the Java test.
 
+java -version
+
 testdir=$(readlink -fn `dirname $0`)
 thisdir=$(readlink -fn `pwd`)
 
+targetdir=${testdir}/target
+
 if [[ "$testdir" != "$thisdir" ]]; then
 	echo error: must be run from inside the ${testdir} directory
 	echo you ran it from ${thisdir}
 	exit 1
 fi
 
-javac -classpath ${testdir}/../java:${testdir}:${testdir}/namespace_test JavaTest.java
-java -classpath ${testdir}/../java:${testdir}:${testdir}/namespace_test JavaTest
+find .. -type f -name "*.class" -exec rm  {} \;
+
+if [[ -e "${targetdir}" ]]; then
+    echo "clean target"
+    rm -rf ${targetdir}
+fi
+
+mkdir ${targetdir}
+
+javac -d ${targetdir} -classpath ${testdir}/../java:${testdir}:${testdir}/namespace_test JavaTest.java
+java -classpath ${targetdir} JavaTest
+
+rm -rf ${targetdir}
diff --git a/tests/MyGame/Example/Monster.cs b/tests/MyGame/Example/Monster.cs
index fdfd2b0..30f4922 100644
--- a/tests/MyGame/Example/Monster.cs
+++ b/tests/MyGame/Example/Monster.cs
@@ -7,79 +7,77 @@
 using FlatBuffers;
 
 /// an example documentation comment: monster object
-public sealed class Monster : Table {
+public struct Monster : IFlatbufferObject
+{
+  private Table __p;
+  public ByteBuffer ByteBuffer { get { return __p.bb; } }
   public static Monster GetRootAsMonster(ByteBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); }
-  public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
-  public static bool MonsterBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "MONS"); }
-  public Monster __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+  public static bool MonsterBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "MONS"); }
+  public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
+  public Monster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
-  public Vec3 Pos { get { return GetPos(new Vec3()); } }
-  public Vec3 GetPos(Vec3 obj) { int o = __offset(4); return o != 0 ? obj.__init(o + bb_pos, bb) : null; }
-  public short Mana { get { int o = __offset(6); return o != 0 ? bb.GetShort(o + bb_pos) : (short)150; } }
-  public bool MutateMana(short mana) { int o = __offset(6); if (o != 0) { bb.PutShort(o + bb_pos, mana); return true; } else { return false; } }
-  public short Hp { get { int o = __offset(8); return o != 0 ? bb.GetShort(o + bb_pos) : (short)100; } }
-  public bool MutateHp(short hp) { int o = __offset(8); if (o != 0) { bb.PutShort(o + bb_pos, hp); return true; } else { return false; } }
-  public string Name { get { int o = __offset(10); return o != 0 ? __string(o + bb_pos) : null; } }
-  public ArraySegment<byte>? GetNameBytes() { return __vector_as_arraysegment(10); }
-  public byte GetInventory(int j) { int o = __offset(14); return o != 0 ? bb.Get(__vector(o) + j * 1) : (byte)0; }
-  public int InventoryLength { get { int o = __offset(14); return o != 0 ? __vector_len(o) : 0; } }
-  public ArraySegment<byte>? GetInventoryBytes() { return __vector_as_arraysegment(14); }
-  public bool MutateInventory(int j, byte inventory) { int o = __offset(14); if (o != 0) { bb.Put(__vector(o) + j * 1, inventory); return true; } else { return false; } }
-  public Color Color { get { int o = __offset(16); return o != 0 ? (Color)bb.GetSbyte(o + bb_pos) : Color.Blue; } }
-  public bool MutateColor(Color color) { int o = __offset(16); if (o != 0) { bb.PutSbyte(o + bb_pos, (sbyte)color); return true; } else { return false; } }
-  public Any TestType { get { int o = __offset(18); return o != 0 ? (Any)bb.Get(o + bb_pos) : Any.NONE; } }
-  public bool MutateTestType(Any test_type) { int o = __offset(18); if (o != 0) { bb.Put(o + bb_pos, (byte)test_type); return true; } else { return false; } }
-  public TTable GetTest<TTable>(TTable obj) where TTable : Table { int o = __offset(20); return o != 0 ? __union(obj, o) : null; }
-  public Test GetTest4(int j) { return GetTest4(new Test(), j); }
-  public Test GetTest4(Test obj, int j) { int o = __offset(22); return o != 0 ? obj.__init(__vector(o) + j * 4, bb) : null; }
-  public int Test4Length { get { int o = __offset(22); return o != 0 ? __vector_len(o) : 0; } }
-  public string GetTestarrayofstring(int j) { int o = __offset(24); return o != 0 ? __string(__vector(o) + j * 4) : null; }
-  public int TestarrayofstringLength { get { int o = __offset(24); return o != 0 ? __vector_len(o) : 0; } }
+  public Vec3? Pos { get { int o = __p.__offset(4); return o != 0 ? (Vec3?)(new Vec3()).__assign(o + __p.bb_pos, __p.bb) : null; } }
+  public short Mana { get { int o = __p.__offset(6); return o != 0 ? __p.bb.GetShort(o + __p.bb_pos) : (short)150; } }
+  public bool MutateMana(short mana) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutShort(o + __p.bb_pos, mana); return true; } else { return false; } }
+  public short Hp { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetShort(o + __p.bb_pos) : (short)100; } }
+  public bool MutateHp(short hp) { int o = __p.__offset(8); if (o != 0) { __p.bb.PutShort(o + __p.bb_pos, hp); return true; } else { return false; } }
+  public string Name { get { int o = __p.__offset(10); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
+  public ArraySegment<byte>? GetNameBytes() { return __p.__vector_as_arraysegment(10); }
+  public byte Inventory(int j) { int o = __p.__offset(14); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; }
+  public int InventoryLength { get { int o = __p.__offset(14); return o != 0 ? __p.__vector_len(o) : 0; } }
+  public ArraySegment<byte>? GetInventoryBytes() { return __p.__vector_as_arraysegment(14); }
+  public bool MutateInventory(int j, byte inventory) { int o = __p.__offset(14); if (o != 0) { __p.bb.Put(__p.__vector(o) + j * 1, inventory); return true; } else { return false; } }
+  public Color Color { get { int o = __p.__offset(16); return o != 0 ? (Color)__p.bb.GetSbyte(o + __p.bb_pos) : Color.Blue; } }
+  public bool MutateColor(Color color) { int o = __p.__offset(16); if (o != 0) { __p.bb.PutSbyte(o + __p.bb_pos, (sbyte)color); return true; } else { return false; } }
+  public Any TestType { get { int o = __p.__offset(18); return o != 0 ? (Any)__p.bb.Get(o + __p.bb_pos) : Any.NONE; } }
+  public bool MutateTestType(Any test_type) { int o = __p.__offset(18); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (byte)test_type); return true; } else { return false; } }
+  public TTable? Test<TTable>() where TTable : struct, IFlatbufferObject { int o = __p.__offset(20); return o != 0 ? (TTable?)__p.__union<TTable>(o) : null; }
+  public Test? Test4(int j) { int o = __p.__offset(22); return o != 0 ? (Test?)(new Test()).__assign(__p.__vector(o) + j * 4, __p.bb) : null; }
+  public int Test4Length { get { int o = __p.__offset(22); return o != 0 ? __p.__vector_len(o) : 0; } }
+  public string Testarrayofstring(int j) { int o = __p.__offset(24); return o != 0 ? __p.__string(__p.__vector(o) + j * 4) : null; }
+  public int TestarrayofstringLength { get { int o = __p.__offset(24); return o != 0 ? __p.__vector_len(o) : 0; } }
   /// an example documentation comment: this will end up in the generated code
   /// multiline too
-  public Monster GetTestarrayoftables(int j) { return GetTestarrayoftables(new Monster(), j); }
-  public Monster GetTestarrayoftables(Monster obj, int j) { int o = __offset(26); return o != 0 ? obj.__init(__indirect(__vector(o) + j * 4), bb) : null; }
-  public int TestarrayoftablesLength { get { int o = __offset(26); return o != 0 ? __vector_len(o) : 0; } }
-  public Monster Enemy { get { return GetEnemy(new Monster()); } }
-  public Monster GetEnemy(Monster obj) { int o = __offset(28); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
-  public byte GetTestnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.Get(__vector(o) + j * 1) : (byte)0; }
-  public int TestnestedflatbufferLength { get { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } }
-  public ArraySegment<byte>? GetTestnestedflatbufferBytes() { return __vector_as_arraysegment(30); }
-  public Monster TestnestedflatbufferAsMonster() { return GetTestnestedflatbufferAsMonster(new Monster()); }
-  public Monster GetTestnestedflatbufferAsMonster(Monster obj) { int o = __offset(30); return o != 0 ? obj.__init(__indirect(__vector(o)), bb) : null; }
-  public bool MutateTestnestedflatbuffer(int j, byte testnestedflatbuffer) { int o = __offset(30); if (o != 0) { bb.Put(__vector(o) + j * 1, testnestedflatbuffer); return true; } else { return false; } }
-  public Stat Testempty { get { return GetTestempty(new Stat()); } }
-  public Stat GetTestempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
-  public bool Testbool { get { int o = __offset(34); return o != 0 ? 0!=bb.Get(o + bb_pos) : (bool)false; } }
-  public bool MutateTestbool(bool testbool) { int o = __offset(34); if (o != 0) { bb.Put(o + bb_pos, (byte)(testbool ? 1 : 0)); return true; } else { return false; } }
-  public int Testhashs32Fnv1 { get { int o = __offset(36); return o != 0 ? bb.GetInt(o + bb_pos) : (int)0; } }
-  public bool MutateTesthashs32Fnv1(int testhashs32_fnv1) { int o = __offset(36); if (o != 0) { bb.PutInt(o + bb_pos, testhashs32_fnv1); return true; } else { return false; } }
-  public uint Testhashu32Fnv1 { get { int o = __offset(38); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
-  public bool MutateTesthashu32Fnv1(uint testhashu32_fnv1) { int o = __offset(38); if (o != 0) { bb.PutUint(o + bb_pos, testhashu32_fnv1); return true; } else { return false; } }
-  public long Testhashs64Fnv1 { get { int o = __offset(40); return o != 0 ? bb.GetLong(o + bb_pos) : (long)0; } }
-  public bool MutateTesthashs64Fnv1(long testhashs64_fnv1) { int o = __offset(40); if (o != 0) { bb.PutLong(o + bb_pos, testhashs64_fnv1); return true; } else { return false; } }
-  public ulong Testhashu64Fnv1 { get { int o = __offset(42); return o != 0 ? bb.GetUlong(o + bb_pos) : (ulong)0; } }
-  public bool MutateTesthashu64Fnv1(ulong testhashu64_fnv1) { int o = __offset(42); if (o != 0) { bb.PutUlong(o + bb_pos, testhashu64_fnv1); return true; } else { return false; } }
-  public int Testhashs32Fnv1a { get { int o = __offset(44); return o != 0 ? bb.GetInt(o + bb_pos) : (int)0; } }
-  public bool MutateTesthashs32Fnv1a(int testhashs32_fnv1a) { int o = __offset(44); if (o != 0) { bb.PutInt(o + bb_pos, testhashs32_fnv1a); return true; } else { return false; } }
-  public uint Testhashu32Fnv1a { get { int o = __offset(46); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
-  public bool MutateTesthashu32Fnv1a(uint testhashu32_fnv1a) { int o = __offset(46); if (o != 0) { bb.PutUint(o + bb_pos, testhashu32_fnv1a); return true; } else { return false; } }
-  public long Testhashs64Fnv1a { get { int o = __offset(48); return o != 0 ? bb.GetLong(o + bb_pos) : (long)0; } }
-  public bool MutateTesthashs64Fnv1a(long testhashs64_fnv1a) { int o = __offset(48); if (o != 0) { bb.PutLong(o + bb_pos, testhashs64_fnv1a); return true; } else { return false; } }
-  public ulong Testhashu64Fnv1a { get { int o = __offset(50); return o != 0 ? bb.GetUlong(o + bb_pos) : (ulong)0; } }
-  public bool MutateTesthashu64Fnv1a(ulong testhashu64_fnv1a) { int o = __offset(50); if (o != 0) { bb.PutUlong(o + bb_pos, testhashu64_fnv1a); return true; } else { return false; } }
-  public bool GetTestarrayofbools(int j) { int o = __offset(52); return o != 0 ? 0!=bb.Get(__vector(o) + j * 1) : false; }
-  public int TestarrayofboolsLength { get { int o = __offset(52); return o != 0 ? __vector_len(o) : 0; } }
-  public ArraySegment<byte>? GetTestarrayofboolsBytes() { return __vector_as_arraysegment(52); }
-  public bool MutateTestarrayofbools(int j, bool testarrayofbools) { int o = __offset(52); if (o != 0) { bb.Put(__vector(o) + j * 1, (byte)(testarrayofbools ? 1 : 0)); return true; } else { return false; } }
-  public float Testf { get { int o = __offset(54); return o != 0 ? bb.GetFloat(o + bb_pos) : (float)3.14159f; } }
-  public bool MutateTestf(float testf) { int o = __offset(54); if (o != 0) { bb.PutFloat(o + bb_pos, testf); return true; } else { return false; } }
-  public float Testf2 { get { int o = __offset(56); return o != 0 ? bb.GetFloat(o + bb_pos) : (float)3.0f; } }
-  public bool MutateTestf2(float testf2) { int o = __offset(56); if (o != 0) { bb.PutFloat(o + bb_pos, testf2); return true; } else { return false; } }
-  public float Testf3 { get { int o = __offset(58); return o != 0 ? bb.GetFloat(o + bb_pos) : (float)0.0f; } }
-  public bool MutateTestf3(float testf3) { int o = __offset(58); if (o != 0) { bb.PutFloat(o + bb_pos, testf3); return true; } else { return false; } }
-  public string GetTestarrayofstring2(int j) { int o = __offset(60); return o != 0 ? __string(__vector(o) + j * 4) : null; }
-  public int Testarrayofstring2Length { get { int o = __offset(60); return o != 0 ? __vector_len(o) : 0; } }
+  public Monster? Testarrayoftables(int j) { int o = __p.__offset(26); return o != 0 ? (Monster?)(new Monster()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; }
+  public int TestarrayoftablesLength { get { int o = __p.__offset(26); return o != 0 ? __p.__vector_len(o) : 0; } }
+  public Monster? Enemy { get { int o = __p.__offset(28); return o != 0 ? (Monster?)(new Monster()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
+  public byte Testnestedflatbuffer(int j) { int o = __p.__offset(30); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; }
+  public int TestnestedflatbufferLength { get { int o = __p.__offset(30); return o != 0 ? __p.__vector_len(o) : 0; } }
+  public ArraySegment<byte>? GetTestnestedflatbufferBytes() { return __p.__vector_as_arraysegment(30); }
+  public Monster? GetTestnestedflatbufferAsMonster() { int o = __p.__offset(30); return o != 0 ? (Monster?)(new Monster()).__assign(__p.__indirect(__p.__vector(o)), __p.bb) : null; }
+  public bool MutateTestnestedflatbuffer(int j, byte testnestedflatbuffer) { int o = __p.__offset(30); if (o != 0) { __p.bb.Put(__p.__vector(o) + j * 1, testnestedflatbuffer); return true; } else { return false; } }
+  public Stat? Testempty { get { int o = __p.__offset(32); return o != 0 ? (Stat?)(new Stat()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
+  public bool Testbool { get { int o = __p.__offset(34); return o != 0 ? 0!=__p.bb.Get(o + __p.bb_pos) : (bool)false; } }
+  public bool MutateTestbool(bool testbool) { int o = __p.__offset(34); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (byte)(testbool ? 1 : 0)); return true; } else { return false; } }
+  public int Testhashs32Fnv1 { get { int o = __p.__offset(36); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
+  public bool MutateTesthashs32Fnv1(int testhashs32_fnv1) { int o = __p.__offset(36); if (o != 0) { __p.bb.PutInt(o + __p.bb_pos, testhashs32_fnv1); return true; } else { return false; } }
+  public uint Testhashu32Fnv1 { get { int o = __p.__offset(38); return o != 0 ? __p.bb.GetUint(o + __p.bb_pos) : (uint)0; } }
+  public bool MutateTesthashu32Fnv1(uint testhashu32_fnv1) { int o = __p.__offset(38); if (o != 0) { __p.bb.PutUint(o + __p.bb_pos, testhashu32_fnv1); return true; } else { return false; } }
+  public long Testhashs64Fnv1 { get { int o = __p.__offset(40); return o != 0 ? __p.bb.GetLong(o + __p.bb_pos) : (long)0; } }
+  public bool MutateTesthashs64Fnv1(long testhashs64_fnv1) { int o = __p.__offset(40); if (o != 0) { __p.bb.PutLong(o + __p.bb_pos, testhashs64_fnv1); return true; } else { return false; } }
+  public ulong Testhashu64Fnv1 { get { int o = __p.__offset(42); return o != 0 ? __p.bb.GetUlong(o + __p.bb_pos) : (ulong)0; } }
+  public bool MutateTesthashu64Fnv1(ulong testhashu64_fnv1) { int o = __p.__offset(42); if (o != 0) { __p.bb.PutUlong(o + __p.bb_pos, testhashu64_fnv1); return true; } else { return false; } }
+  public int Testhashs32Fnv1a { get { int o = __p.__offset(44); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
+  public bool MutateTesthashs32Fnv1a(int testhashs32_fnv1a) { int o = __p.__offset(44); if (o != 0) { __p.bb.PutInt(o + __p.bb_pos, testhashs32_fnv1a); return true; } else { return false; } }
+  public uint Testhashu32Fnv1a { get { int o = __p.__offset(46); return o != 0 ? __p.bb.GetUint(o + __p.bb_pos) : (uint)0; } }
+  public bool MutateTesthashu32Fnv1a(uint testhashu32_fnv1a) { int o = __p.__offset(46); if (o != 0) { __p.bb.PutUint(o + __p.bb_pos, testhashu32_fnv1a); return true; } else { return false; } }
+  public long Testhashs64Fnv1a { get { int o = __p.__offset(48); return o != 0 ? __p.bb.GetLong(o + __p.bb_pos) : (long)0; } }
+  public bool MutateTesthashs64Fnv1a(long testhashs64_fnv1a) { int o = __p.__offset(48); if (o != 0) { __p.bb.PutLong(o + __p.bb_pos, testhashs64_fnv1a); return true; } else { return false; } }
+  public ulong Testhashu64Fnv1a { get { int o = __p.__offset(50); return o != 0 ? __p.bb.GetUlong(o + __p.bb_pos) : (ulong)0; } }
+  public bool MutateTesthashu64Fnv1a(ulong testhashu64_fnv1a) { int o = __p.__offset(50); if (o != 0) { __p.bb.PutUlong(o + __p.bb_pos, testhashu64_fnv1a); return true; } else { return false; } }
+  public bool Testarrayofbools(int j) { int o = __p.__offset(52); return o != 0 ? 0!=__p.bb.Get(__p.__vector(o) + j * 1) : false; }
+  public int TestarrayofboolsLength { get { int o = __p.__offset(52); return o != 0 ? __p.__vector_len(o) : 0; } }
+  public ArraySegment<byte>? GetTestarrayofboolsBytes() { return __p.__vector_as_arraysegment(52); }
+  public bool MutateTestarrayofbools(int j, bool testarrayofbools) { int o = __p.__offset(52); if (o != 0) { __p.bb.Put(__p.__vector(o) + j * 1, (byte)(testarrayofbools ? 1 : 0)); return true; } else { return false; } }
+  public float Testf { get { int o = __p.__offset(54); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)3.14159f; } }
+  public bool MutateTestf(float testf) { int o = __p.__offset(54); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, testf); return true; } else { return false; } }
+  public float Testf2 { get { int o = __p.__offset(56); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)3.0f; } }
+  public bool MutateTestf2(float testf2) { int o = __p.__offset(56); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, testf2); return true; } else { return false; } }
+  public float Testf3 { get { int o = __p.__offset(58); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)0.0f; } }
+  public bool MutateTestf3(float testf3) { int o = __p.__offset(58); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, testf3); return true; } else { return false; } }
+  public string Testarrayofstring2(int j) { int o = __p.__offset(60); return o != 0 ? __p.__string(__p.__vector(o) + j * 4) : null; }
+  public int Testarrayofstring2Length { get { int o = __p.__offset(60); return o != 0 ? __p.__vector_len(o) : 0; } }
 
   public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(29); }
   public static void AddPos(FlatBufferBuilder builder, Offset<Vec3> posOffset) { builder.AddStruct(0, posOffset.Value, 0); }
@@ -129,6 +127,34 @@
     return new Offset<Monster>(o);
   }
   public static void FinishMonsterBuffer(FlatBufferBuilder builder, Offset<Monster> offset) { builder.Finish(offset.Value, "MONS"); }
+
+  public static VectorOffset CreateMySortedVectorOfTables(FlatBufferBuilder builder, Offset<Monster>[] offsets) {
+    Array.Sort(offsets, (Offset<Monster> o1, Offset<Monster> o2) => Table.CompareStrings(Table.__offset(10, o1.Value, builder.DataBuffer), Table.__offset(10, o2.Value, builder.DataBuffer), builder.DataBuffer));
+    return builder.CreateVectorOfTables(offsets);
+  }
+
+  public static Monster? LookupByKey(VectorOffset vectorOffset, string key, ByteBuffer bb) {
+    byte[] byteKey = System.Text.Encoding.UTF8.GetBytes(key);
+    int vectorLocation = bb.Length - vectorOffset.Value;
+    int span = bb.GetInt(vectorLocation);
+    int start = 0;
+    vectorLocation += 4;
+    while (span != 0) {
+      int middle = span / 2;
+      int tableOffset = Table.__indirect(vectorLocation + 4 * (start + middle), bb);
+      int comp = Table.CompareStrings(Table.__offset(10, bb.Length - tableOffset, bb), byteKey, bb);
+      if (comp > 0) {
+        span = middle;
+      } else if (comp < 0) {
+        middle++;
+        start += middle;
+        span -= middle;
+      } else {
+        return new Monster().__assign(tableOffset, bb);
+      }
+    }
+    return null;
+  }
 };
 
 
diff --git a/tests/MyGame/Example/Monster.java b/tests/MyGame/Example/Monster.java
index dc27f84..b68e625 100644
--- a/tests/MyGame/Example/Monster.java
+++ b/tests/MyGame/Example/Monster.java
@@ -13,12 +13,13 @@
  */
 public final class Monster extends Table {
   public static Monster getRootAsMonster(ByteBuffer _bb) { return getRootAsMonster(_bb, new Monster()); }
-  public static Monster getRootAsMonster(ByteBuffer _bb, Monster obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
+  public static Monster getRootAsMonster(ByteBuffer _bb, Monster obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
   public static boolean MonsterBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "MONS"); }
-  public Monster __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
+  public Monster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
   public Vec3 pos() { return pos(new Vec3()); }
-  public Vec3 pos(Vec3 obj) { int o = __offset(4); return o != 0 ? obj.__init(o + bb_pos, bb) : null; }
+  public Vec3 pos(Vec3 obj) { int o = __offset(4); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; }
   public short mana() { int o = __offset(6); return o != 0 ? bb.getShort(o + bb_pos) : 150; }
   public boolean mutateMana(short mana) { int o = __offset(6); if (o != 0) { bb.putShort(o + bb_pos, mana); return true; } else { return false; } }
   public short hp() { int o = __offset(8); return o != 0 ? bb.getShort(o + bb_pos) : 100; }
@@ -35,7 +36,7 @@
   public boolean mutateTestType(byte test_type) { int o = __offset(18); if (o != 0) { bb.put(o + bb_pos, test_type); return true; } else { return false; } }
   public Table test(Table obj) { int o = __offset(20); return o != 0 ? __union(obj, o) : null; }
   public Test test4(int j) { return test4(new Test(), j); }
-  public Test test4(Test obj, int j) { int o = __offset(22); return o != 0 ? obj.__init(__vector(o) + j * 4, bb) : null; }
+  public Test test4(Test obj, int j) { int o = __offset(22); return o != 0 ? obj.__assign(__vector(o) + j * 4, bb) : null; }
   public int test4Length() { int o = __offset(22); return o != 0 ? __vector_len(o) : 0; }
   public String testarrayofstring(int j) { int o = __offset(24); return o != 0 ? __string(__vector(o) + j * 4) : null; }
   public int testarrayofstringLength() { int o = __offset(24); return o != 0 ? __vector_len(o) : 0; }
@@ -44,18 +45,18 @@
    * multiline too
    */
   public Monster testarrayoftables(int j) { return testarrayoftables(new Monster(), j); }
-  public Monster testarrayoftables(Monster obj, int j) { int o = __offset(26); return o != 0 ? obj.__init(__indirect(__vector(o) + j * 4), bb) : null; }
+  public Monster testarrayoftables(Monster obj, int j) { int o = __offset(26); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; }
   public int testarrayoftablesLength() { int o = __offset(26); return o != 0 ? __vector_len(o) : 0; }
   public Monster enemy() { return enemy(new Monster()); }
-  public Monster enemy(Monster obj) { int o = __offset(28); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
+  public Monster enemy(Monster obj) { int o = __offset(28); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; }
   public int testnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0; }
   public int testnestedflatbufferLength() { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; }
   public ByteBuffer testnestedflatbufferAsByteBuffer() { return __vector_as_bytebuffer(30, 1); }
   public Monster testnestedflatbufferAsMonster() { return testnestedflatbufferAsMonster(new Monster()); }
-  public Monster testnestedflatbufferAsMonster(Monster obj) { int o = __offset(30); return o != 0 ? obj.__init(__indirect(__vector(o)), bb) : null; }
+  public Monster testnestedflatbufferAsMonster(Monster obj) { int o = __offset(30); return o != 0 ? obj.__assign(__indirect(__vector(o)), bb) : null; }
   public boolean mutateTestnestedflatbuffer(int j, int testnestedflatbuffer) { int o = __offset(30); if (o != 0) { bb.put(__vector(o) + j * 1, (byte)testnestedflatbuffer); return true; } else { return false; } }
   public Stat testempty() { return testempty(new Stat()); }
-  public Stat testempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
+  public Stat testempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; }
   public boolean testbool() { int o = __offset(34); return o != 0 ? 0!=bb.get(o + bb_pos) : false; }
   public boolean mutateTestbool(boolean testbool) { int o = __offset(34); if (o != 0) { bb.put(o + bb_pos, (byte)(testbool ? 1 : 0)); return true; } else { return false; } }
   public int testhashs32Fnv1() { int o = __offset(36); return o != 0 ? bb.getInt(o + bb_pos) : 0; }
@@ -135,5 +136,31 @@
     return o;
   }
   public static void finishMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset, "MONS"); }
+
+  @Override
+  protected int keysCompare(Integer o1, Integer o2, ByteBuffer _bb) { return compareStrings(__offset(10, o1, _bb), __offset(10, o2, _bb), _bb); }
+
+  public static Monster lookupByKey(int vectorOffset, String key, ByteBuffer bb) {
+    byte[] byteKey = key.getBytes(Table.UTF8_CHARSET.get());
+    int vectorLocation = bb.array().length - vectorOffset;
+    int span = bb.getInt(vectorLocation);
+    int start = 0;
+    vectorLocation += 4;
+    while (span != 0) {
+      int middle = span / 2;
+      int tableOffset = __indirect(vectorLocation + 4 * (start + middle), bb);
+      int comp = compareStrings(__offset(10, bb.array().length - tableOffset, bb), byteKey, bb);
+      if (comp > 0) {
+        span = middle;
+      } else if (comp < 0) {
+        middle++;
+        start += middle;
+        span -= middle;
+      } else {
+        return new Monster().__assign(tableOffset, bb);
+      }
+    }
+    return null;
+  }
 }
 
diff --git a/tests/MyGame/Example/Stat.cs b/tests/MyGame/Example/Stat.cs
index 30eaee5..0fb5bd0 100644
--- a/tests/MyGame/Example/Stat.cs
+++ b/tests/MyGame/Example/Stat.cs
@@ -6,17 +6,21 @@
 using System;
 using FlatBuffers;
 
-public sealed class Stat : Table {
+public struct Stat : IFlatbufferObject
+{
+  private Table __p;
+  public ByteBuffer ByteBuffer { get { return __p.bb; } }
   public static Stat GetRootAsStat(ByteBuffer _bb) { return GetRootAsStat(_bb, new Stat()); }
-  public static Stat GetRootAsStat(ByteBuffer _bb, Stat obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
-  public Stat __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static Stat GetRootAsStat(ByteBuffer _bb, Stat obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
+  public Stat __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
-  public string Id { get { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } }
-  public ArraySegment<byte>? GetIdBytes() { return __vector_as_arraysegment(4); }
-  public long Val { get { int o = __offset(6); return o != 0 ? bb.GetLong(o + bb_pos) : (long)0; } }
-  public bool MutateVal(long val) { int o = __offset(6); if (o != 0) { bb.PutLong(o + bb_pos, val); return true; } else { return false; } }
-  public ushort Count { get { int o = __offset(8); return o != 0 ? bb.GetUshort(o + bb_pos) : (ushort)0; } }
-  public bool MutateCount(ushort count) { int o = __offset(8); if (o != 0) { bb.PutUshort(o + bb_pos, count); return true; } else { return false; } }
+  public string Id { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
+  public ArraySegment<byte>? GetIdBytes() { return __p.__vector_as_arraysegment(4); }
+  public long Val { get { int o = __p.__offset(6); return o != 0 ? __p.bb.GetLong(o + __p.bb_pos) : (long)0; } }
+  public bool MutateVal(long val) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutLong(o + __p.bb_pos, val); return true; } else { return false; } }
+  public ushort Count { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetUshort(o + __p.bb_pos) : (ushort)0; } }
+  public bool MutateCount(ushort count) { int o = __p.__offset(8); if (o != 0) { __p.bb.PutUshort(o + __p.bb_pos, count); return true; } else { return false; } }
 
   public static Offset<Stat> CreateStat(FlatBufferBuilder builder,
       StringOffset idOffset = default(StringOffset),
diff --git a/tests/MyGame/Example/Stat.java b/tests/MyGame/Example/Stat.java
index cd339c6..9a75142 100644
--- a/tests/MyGame/Example/Stat.java
+++ b/tests/MyGame/Example/Stat.java
@@ -10,8 +10,9 @@
 @SuppressWarnings("unused")
 public final class Stat extends Table {
   public static Stat getRootAsStat(ByteBuffer _bb) { return getRootAsStat(_bb, new Stat()); }
-  public static Stat getRootAsStat(ByteBuffer _bb, Stat obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
-  public Stat __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static Stat getRootAsStat(ByteBuffer _bb, Stat obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
+  public Stat __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
   public String id() { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; }
   public ByteBuffer idAsByteBuffer() { return __vector_as_bytebuffer(4, 1); }
diff --git a/tests/MyGame/Example/Test.cs b/tests/MyGame/Example/Test.cs
index bd82295..92c3b91 100644
--- a/tests/MyGame/Example/Test.cs
+++ b/tests/MyGame/Example/Test.cs
@@ -6,13 +6,17 @@
 using System;
 using FlatBuffers;
 
-public sealed class Test : Struct {
-  public Test __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+public struct Test : IFlatbufferObject
+{
+  private Struct __p;
+  public ByteBuffer ByteBuffer { get { return __p.bb; } }
+  public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
+  public Test __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
-  public short A { get { return bb.GetShort(bb_pos + 0); } }
-  public void MutateA(short a) { bb.PutShort(bb_pos + 0, a); }
-  public sbyte B { get { return bb.GetSbyte(bb_pos + 2); } }
-  public void MutateB(sbyte b) { bb.PutSbyte(bb_pos + 2, b); }
+  public short A { get { return __p.bb.GetShort(__p.bb_pos + 0); } }
+  public void MutateA(short a) { __p.bb.PutShort(__p.bb_pos + 0, a); }
+  public sbyte B { get { return __p.bb.GetSbyte(__p.bb_pos + 2); } }
+  public void MutateB(sbyte b) { __p.bb.PutSbyte(__p.bb_pos + 2, b); }
 
   public static Offset<Test> CreateTest(FlatBufferBuilder builder, short A, sbyte B) {
     builder.Prep(2, 4);
diff --git a/tests/MyGame/Example/Test.java b/tests/MyGame/Example/Test.java
index 6e33da9..f584c46 100644
--- a/tests/MyGame/Example/Test.java
+++ b/tests/MyGame/Example/Test.java
@@ -9,7 +9,8 @@
 
 @SuppressWarnings("unused")
 public final class Test extends Struct {
-  public Test __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
+  public Test __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
   public short a() { return bb.getShort(bb_pos + 0); }
   public void mutateA(short a) { bb.putShort(bb_pos + 0, a); }
diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.cs b/tests/MyGame/Example/TestSimpleTableWithEnum.cs
index 63cb9e1..bff3864 100644
--- a/tests/MyGame/Example/TestSimpleTableWithEnum.cs
+++ b/tests/MyGame/Example/TestSimpleTableWithEnum.cs
@@ -6,13 +6,17 @@
 using System;
 using FlatBuffers;
 
-public partial class TestSimpleTableWithEnum : Table {
+public partial struct TestSimpleTableWithEnum : IFlatbufferObject
+{
+  private Table __p;
+  public ByteBuffer ByteBuffer { get { return __p.bb; } }
   public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteBuffer _bb) { return GetRootAsTestSimpleTableWithEnum(_bb, new TestSimpleTableWithEnum()); }
-  public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteBuffer _bb, TestSimpleTableWithEnum obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
-  public TestSimpleTableWithEnum __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteBuffer _bb, TestSimpleTableWithEnum obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
+  public TestSimpleTableWithEnum __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
-  public Color Color { get { int o = __offset(4); return o != 0 ? (Color)bb.GetSbyte(o + bb_pos) : Color.Green; } }
-  public bool MutateColor(Color color) { int o = __offset(4); if (o != 0) { bb.PutSbyte(o + bb_pos, (sbyte)color); return true; } else { return false; } }
+  public Color Color { get { int o = __p.__offset(4); return o != 0 ? (Color)__p.bb.GetSbyte(o + __p.bb_pos) : Color.Green; } }
+  public bool MutateColor(Color color) { int o = __p.__offset(4); if (o != 0) { __p.bb.PutSbyte(o + __p.bb_pos, (sbyte)color); return true; } else { return false; } }
 
   public static Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(FlatBufferBuilder builder,
       Color color = Color.Green) {
diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.java b/tests/MyGame/Example/TestSimpleTableWithEnum.java
index a1de020..9f77b39 100644
--- a/tests/MyGame/Example/TestSimpleTableWithEnum.java
+++ b/tests/MyGame/Example/TestSimpleTableWithEnum.java
@@ -10,8 +10,9 @@
 @SuppressWarnings("unused")
 public final class TestSimpleTableWithEnum extends Table {
   public static TestSimpleTableWithEnum getRootAsTestSimpleTableWithEnum(ByteBuffer _bb) { return getRootAsTestSimpleTableWithEnum(_bb, new TestSimpleTableWithEnum()); }
-  public static TestSimpleTableWithEnum getRootAsTestSimpleTableWithEnum(ByteBuffer _bb, TestSimpleTableWithEnum obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
-  public TestSimpleTableWithEnum __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static TestSimpleTableWithEnum getRootAsTestSimpleTableWithEnum(ByteBuffer _bb, TestSimpleTableWithEnum obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
+  public TestSimpleTableWithEnum __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
   public byte color() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 2; }
   public boolean mutateColor(byte color) { int o = __offset(4); if (o != 0) { bb.put(o + bb_pos, color); return true; } else { return false; } }
diff --git a/tests/MyGame/Example/Vec3.cs b/tests/MyGame/Example/Vec3.cs
index a6d21fa..0552543 100644
--- a/tests/MyGame/Example/Vec3.cs
+++ b/tests/MyGame/Example/Vec3.cs
@@ -6,21 +6,24 @@
 using System;
 using FlatBuffers;
 
-public sealed class Vec3 : Struct {
-  public Vec3 __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+public struct Vec3 : IFlatbufferObject
+{
+  private Struct __p;
+  public ByteBuffer ByteBuffer { get { return __p.bb; } }
+  public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
+  public Vec3 __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
-  public float X { get { return bb.GetFloat(bb_pos + 0); } }
-  public void MutateX(float x) { bb.PutFloat(bb_pos + 0, x); }
-  public float Y { get { return bb.GetFloat(bb_pos + 4); } }
-  public void MutateY(float y) { bb.PutFloat(bb_pos + 4, y); }
-  public float Z { get { return bb.GetFloat(bb_pos + 8); } }
-  public void MutateZ(float z) { bb.PutFloat(bb_pos + 8, z); }
-  public double Test1 { get { return bb.GetDouble(bb_pos + 16); } }
-  public void MutateTest1(double test1) { bb.PutDouble(bb_pos + 16, test1); }
-  public Color Test2 { get { return (Color)bb.GetSbyte(bb_pos + 24); } }
-  public void MutateTest2(Color test2) { bb.PutSbyte(bb_pos + 24, (sbyte)test2); }
-  public Test Test3 { get { return GetTest3(new Test()); } }
-  public Test GetTest3(Test obj) { return obj.__init(bb_pos + 26, bb); }
+  public float X { get { return __p.bb.GetFloat(__p.bb_pos + 0); } }
+  public void MutateX(float x) { __p.bb.PutFloat(__p.bb_pos + 0, x); }
+  public float Y { get { return __p.bb.GetFloat(__p.bb_pos + 4); } }
+  public void MutateY(float y) { __p.bb.PutFloat(__p.bb_pos + 4, y); }
+  public float Z { get { return __p.bb.GetFloat(__p.bb_pos + 8); } }
+  public void MutateZ(float z) { __p.bb.PutFloat(__p.bb_pos + 8, z); }
+  public double Test1 { get { return __p.bb.GetDouble(__p.bb_pos + 16); } }
+  public void MutateTest1(double test1) { __p.bb.PutDouble(__p.bb_pos + 16, test1); }
+  public Color Test2 { get { return (Color)__p.bb.GetSbyte(__p.bb_pos + 24); } }
+  public void MutateTest2(Color test2) { __p.bb.PutSbyte(__p.bb_pos + 24, (sbyte)test2); }
+  public Test Test3 { get { return (new Test()).__assign(__p.bb_pos + 26, __p.bb); } }
 
   public static Offset<Vec3> CreateVec3(FlatBufferBuilder builder, float X, float Y, float Z, double Test1, Color Test2, short test3_A, sbyte test3_B) {
     builder.Prep(16, 32);
diff --git a/tests/MyGame/Example/Vec3.java b/tests/MyGame/Example/Vec3.java
index 261947c..6cb820b 100644
--- a/tests/MyGame/Example/Vec3.java
+++ b/tests/MyGame/Example/Vec3.java
@@ -9,7 +9,8 @@
 
 @SuppressWarnings("unused")
 public final class Vec3 extends Struct {
-  public Vec3 __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
+  public Vec3 __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
   public float x() { return bb.getFloat(bb_pos + 0); }
   public void mutateX(float x) { bb.putFloat(bb_pos + 0, x); }
@@ -22,7 +23,7 @@
   public byte test2() { return bb.get(bb_pos + 24); }
   public void mutateTest2(byte test2) { bb.put(bb_pos + 24, test2); }
   public Test test3() { return test3(new Test()); }
-  public Test test3(Test obj) { return obj.__init(bb_pos + 26, bb); }
+  public Test test3(Test obj) { return obj.__assign(bb_pos + 26, bb); }
 
   public static int createVec3(FlatBufferBuilder builder, float x, float y, float z, double test1, byte test2, short test3_a, byte test3_b) {
     builder.prep(16, 32);
diff --git a/tests/MyGame/Example2/Monster.cs b/tests/MyGame/Example2/Monster.cs
index e6c512a..6b1602e 100644
--- a/tests/MyGame/Example2/Monster.cs
+++ b/tests/MyGame/Example2/Monster.cs
@@ -6,10 +6,14 @@
 using System;
 using FlatBuffers;
 
-public sealed class Monster : Table {
+public struct Monster : IFlatbufferObject
+{
+  private Table __p;
+  public ByteBuffer ByteBuffer { get { return __p.bb; } }
   public static Monster GetRootAsMonster(ByteBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); }
-  public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
-  public Monster __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
+  public Monster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
 
   public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(0); }
diff --git a/tests/MyGame/Example2/Monster.java b/tests/MyGame/Example2/Monster.java
index 968eee5..69a1562 100644
--- a/tests/MyGame/Example2/Monster.java
+++ b/tests/MyGame/Example2/Monster.java
@@ -10,8 +10,9 @@
 @SuppressWarnings("unused")
 public final class Monster extends Table {
   public static Monster getRootAsMonster(ByteBuffer _bb) { return getRootAsMonster(_bb, new Monster()); }
-  public static Monster getRootAsMonster(ByteBuffer _bb, Monster obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
-  public Monster __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static Monster getRootAsMonster(ByteBuffer _bb, Monster obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
+  public Monster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
 
   public static void startMonster(FlatBufferBuilder builder) { builder.startObject(0); }
diff --git a/tests/generate_code.bat b/tests/generate_code.bat
index 4b4a535..e7660a2 100644
--- a/tests/generate_code.bat
+++ b/tests/generate_code.bat
@@ -12,6 +12,9 @@
 :: See the License for the specific language governing permissions and
 :: limitations under the License.
 
-..\flatc.exe --cpp --java --csharp --go --binary --python --js --php --grpc --gen-mutable --gen-object-api --no-includes monster_test.fbs monsterdata_test.json
-..\flatc.exe --cpp --java --csharp --go --binary --python --js --php --gen-mutable -o namespace_test namespace_test\namespace_test1.fbs namespace_test\namespace_test2.fbs
-..\flatc.exe --binary --schema monster_test.fbs
+set buildtype=Release
+if "%1"=="-b" set buildtype=%2
+
+..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --js --php --grpc --gen-mutable --gen-object-api --no-includes monster_test.fbs monsterdata_test.json
+..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --js --php --gen-mutable -o namespace_test namespace_test\namespace_test1.fbs namespace_test\namespace_test2.fbs
+..\%buildtype%\flatc.exe --binary --schema monster_test.fbs
diff --git a/tests/generate_code.sh b/tests/generate_code.sh
old mode 100644
new mode 100755
diff --git a/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.cs b/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.cs
index 16b0f45..508895f 100644
--- a/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.cs
+++ b/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.cs
@@ -6,13 +6,17 @@
 using System;
 using FlatBuffers;
 
-public sealed class StructInNestedNS : Struct {
-  public StructInNestedNS __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+public struct StructInNestedNS : IFlatbufferObject
+{
+  private Struct __p;
+  public ByteBuffer ByteBuffer { get { return __p.bb; } }
+  public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
+  public StructInNestedNS __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
-  public int A { get { return bb.GetInt(bb_pos + 0); } }
-  public void MutateA(int a) { bb.PutInt(bb_pos + 0, a); }
-  public int B { get { return bb.GetInt(bb_pos + 4); } }
-  public void MutateB(int b) { bb.PutInt(bb_pos + 4, b); }
+  public int A { get { return __p.bb.GetInt(__p.bb_pos + 0); } }
+  public void MutateA(int a) { __p.bb.PutInt(__p.bb_pos + 0, a); }
+  public int B { get { return __p.bb.GetInt(__p.bb_pos + 4); } }
+  public void MutateB(int b) { __p.bb.PutInt(__p.bb_pos + 4, b); }
 
   public static Offset<StructInNestedNS> CreateStructInNestedNS(FlatBufferBuilder builder, int A, int B) {
     builder.Prep(4, 8);
diff --git a/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.java b/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.java
index fede07a..42d47c1 100644
--- a/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.java
+++ b/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.java
@@ -9,7 +9,8 @@
 
 @SuppressWarnings("unused")
 public final class StructInNestedNS extends Struct {
-  public StructInNestedNS __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
+  public StructInNestedNS __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
   public int a() { return bb.getInt(bb_pos + 0); }
   public void mutateA(int a) { bb.putInt(bb_pos + 0, a); }
diff --git a/tests/namespace_test/NamespaceA/NamespaceB/TableInNestedNS.cs b/tests/namespace_test/NamespaceA/NamespaceB/TableInNestedNS.cs
index b983cd0..a2a1c0b 100644
--- a/tests/namespace_test/NamespaceA/NamespaceB/TableInNestedNS.cs
+++ b/tests/namespace_test/NamespaceA/NamespaceB/TableInNestedNS.cs
@@ -6,13 +6,17 @@
 using System;
 using FlatBuffers;
 
-public sealed class TableInNestedNS : Table {
+public struct TableInNestedNS : IFlatbufferObject
+{
+  private Table __p;
+  public ByteBuffer ByteBuffer { get { return __p.bb; } }
   public static TableInNestedNS GetRootAsTableInNestedNS(ByteBuffer _bb) { return GetRootAsTableInNestedNS(_bb, new TableInNestedNS()); }
-  public static TableInNestedNS GetRootAsTableInNestedNS(ByteBuffer _bb, TableInNestedNS obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
-  public TableInNestedNS __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static TableInNestedNS GetRootAsTableInNestedNS(ByteBuffer _bb, TableInNestedNS obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
+  public TableInNestedNS __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
-  public int Foo { get { int o = __offset(4); return o != 0 ? bb.GetInt(o + bb_pos) : (int)0; } }
-  public bool MutateFoo(int foo) { int o = __offset(4); if (o != 0) { bb.PutInt(o + bb_pos, foo); return true; } else { return false; } }
+  public int Foo { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
+  public bool MutateFoo(int foo) { int o = __p.__offset(4); if (o != 0) { __p.bb.PutInt(o + __p.bb_pos, foo); return true; } else { return false; } }
 
   public static Offset<TableInNestedNS> CreateTableInNestedNS(FlatBufferBuilder builder,
       int foo = 0) {
diff --git a/tests/namespace_test/NamespaceA/NamespaceB/TableInNestedNS.java b/tests/namespace_test/NamespaceA/NamespaceB/TableInNestedNS.java
index fc51856..415fa69 100644
--- a/tests/namespace_test/NamespaceA/NamespaceB/TableInNestedNS.java
+++ b/tests/namespace_test/NamespaceA/NamespaceB/TableInNestedNS.java
@@ -10,8 +10,9 @@
 @SuppressWarnings("unused")
 public final class TableInNestedNS extends Table {
   public static TableInNestedNS getRootAsTableInNestedNS(ByteBuffer _bb) { return getRootAsTableInNestedNS(_bb, new TableInNestedNS()); }
-  public static TableInNestedNS getRootAsTableInNestedNS(ByteBuffer _bb, TableInNestedNS obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
-  public TableInNestedNS __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static TableInNestedNS getRootAsTableInNestedNS(ByteBuffer _bb, TableInNestedNS obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
+  public TableInNestedNS __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
   public int foo() { int o = __offset(4); return o != 0 ? bb.getInt(o + bb_pos) : 0; }
   public boolean mutateFoo(int foo) { int o = __offset(4); if (o != 0) { bb.putInt(o + bb_pos, foo); return true; } else { return false; } }
diff --git a/tests/namespace_test/NamespaceA/SecondTableInA.cs b/tests/namespace_test/NamespaceA/SecondTableInA.cs
index 96ae378..2048828 100644
--- a/tests/namespace_test/NamespaceA/SecondTableInA.cs
+++ b/tests/namespace_test/NamespaceA/SecondTableInA.cs
@@ -6,13 +6,16 @@
 using System;
 using FlatBuffers;
 
-public sealed class SecondTableInA : Table {
+public struct SecondTableInA : IFlatbufferObject
+{
+  private Table __p;
+  public ByteBuffer ByteBuffer { get { return __p.bb; } }
   public static SecondTableInA GetRootAsSecondTableInA(ByteBuffer _bb) { return GetRootAsSecondTableInA(_bb, new SecondTableInA()); }
-  public static SecondTableInA GetRootAsSecondTableInA(ByteBuffer _bb, SecondTableInA obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
-  public SecondTableInA __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static SecondTableInA GetRootAsSecondTableInA(ByteBuffer _bb, SecondTableInA obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
+  public SecondTableInA __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
-  public NamespaceC.TableInC ReferToC { get { return GetReferToC(new NamespaceC.TableInC()); } }
-  public NamespaceC.TableInC GetReferToC(NamespaceC.TableInC obj) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
+  public NamespaceC.TableInC? ReferToC { get { int o = __p.__offset(4); return o != 0 ? (NamespaceC.TableInC?)(new NamespaceC.TableInC()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
 
   public static Offset<SecondTableInA> CreateSecondTableInA(FlatBufferBuilder builder,
       Offset<NamespaceC.TableInC> refer_to_cOffset = default(Offset<NamespaceC.TableInC>)) {
diff --git a/tests/namespace_test/NamespaceA/SecondTableInA.java b/tests/namespace_test/NamespaceA/SecondTableInA.java
index e6f390a..7c56b88 100644
--- a/tests/namespace_test/NamespaceA/SecondTableInA.java
+++ b/tests/namespace_test/NamespaceA/SecondTableInA.java
@@ -10,11 +10,12 @@
 @SuppressWarnings("unused")
 public final class SecondTableInA extends Table {
   public static SecondTableInA getRootAsSecondTableInA(ByteBuffer _bb) { return getRootAsSecondTableInA(_bb, new SecondTableInA()); }
-  public static SecondTableInA getRootAsSecondTableInA(ByteBuffer _bb, SecondTableInA obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
-  public SecondTableInA __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static SecondTableInA getRootAsSecondTableInA(ByteBuffer _bb, SecondTableInA obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
+  public SecondTableInA __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
   public NamespaceC.TableInC referToC() { return referToC(new NamespaceC.TableInC()); }
-  public NamespaceC.TableInC referToC(NamespaceC.TableInC obj) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
+  public NamespaceC.TableInC referToC(NamespaceC.TableInC obj) { int o = __offset(4); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; }
 
   public static int createSecondTableInA(FlatBufferBuilder builder,
       int refer_to_cOffset) {
diff --git a/tests/namespace_test/NamespaceA/TableInFirstNS.cs b/tests/namespace_test/NamespaceA/TableInFirstNS.cs
index 4b4be11..f1c7e96 100644
--- a/tests/namespace_test/NamespaceA/TableInFirstNS.cs
+++ b/tests/namespace_test/NamespaceA/TableInFirstNS.cs
@@ -6,17 +6,19 @@
 using System;
 using FlatBuffers;
 
-public sealed class TableInFirstNS : Table {
+public struct TableInFirstNS : IFlatbufferObject
+{
+  private Table __p;
+  public ByteBuffer ByteBuffer { get { return __p.bb; } }
   public static TableInFirstNS GetRootAsTableInFirstNS(ByteBuffer _bb) { return GetRootAsTableInFirstNS(_bb, new TableInFirstNS()); }
-  public static TableInFirstNS GetRootAsTableInFirstNS(ByteBuffer _bb, TableInFirstNS obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
-  public TableInFirstNS __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static TableInFirstNS GetRootAsTableInFirstNS(ByteBuffer _bb, TableInFirstNS obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
+  public TableInFirstNS __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
-  public NamespaceA.NamespaceB.TableInNestedNS FooTable { get { return GetFooTable(new NamespaceA.NamespaceB.TableInNestedNS()); } }
-  public NamespaceA.NamespaceB.TableInNestedNS GetFooTable(NamespaceA.NamespaceB.TableInNestedNS obj) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
-  public NamespaceA.NamespaceB.EnumInNestedNS FooEnum { get { int o = __offset(6); return o != 0 ? (NamespaceA.NamespaceB.EnumInNestedNS)bb.GetSbyte(o + bb_pos) : NamespaceA.NamespaceB.EnumInNestedNS.A; } }
-  public bool MutateFooEnum(NamespaceA.NamespaceB.EnumInNestedNS foo_enum) { int o = __offset(6); if (o != 0) { bb.PutSbyte(o + bb_pos, (sbyte)foo_enum); return true; } else { return false; } }
-  public NamespaceA.NamespaceB.StructInNestedNS FooStruct { get { return GetFooStruct(new NamespaceA.NamespaceB.StructInNestedNS()); } }
-  public NamespaceA.NamespaceB.StructInNestedNS GetFooStruct(NamespaceA.NamespaceB.StructInNestedNS obj) { int o = __offset(8); return o != 0 ? obj.__init(o + bb_pos, bb) : null; }
+  public NamespaceA.NamespaceB.TableInNestedNS? FooTable { get { int o = __p.__offset(4); return o != 0 ? (NamespaceA.NamespaceB.TableInNestedNS?)(new NamespaceA.NamespaceB.TableInNestedNS()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
+  public NamespaceA.NamespaceB.EnumInNestedNS FooEnum { get { int o = __p.__offset(6); return o != 0 ? (NamespaceA.NamespaceB.EnumInNestedNS)__p.bb.GetSbyte(o + __p.bb_pos) : NamespaceA.NamespaceB.EnumInNestedNS.A; } }
+  public bool MutateFooEnum(NamespaceA.NamespaceB.EnumInNestedNS foo_enum) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutSbyte(o + __p.bb_pos, (sbyte)foo_enum); return true; } else { return false; } }
+  public NamespaceA.NamespaceB.StructInNestedNS? FooStruct { get { int o = __p.__offset(8); return o != 0 ? (NamespaceA.NamespaceB.StructInNestedNS?)(new NamespaceA.NamespaceB.StructInNestedNS()).__assign(o + __p.bb_pos, __p.bb) : null; } }
 
   public static void StartTableInFirstNS(FlatBufferBuilder builder) { builder.StartObject(3); }
   public static void AddFooTable(FlatBufferBuilder builder, Offset<NamespaceA.NamespaceB.TableInNestedNS> fooTableOffset) { builder.AddOffset(0, fooTableOffset.Value, 0); }
diff --git a/tests/namespace_test/NamespaceA/TableInFirstNS.java b/tests/namespace_test/NamespaceA/TableInFirstNS.java
index b44df97..b03c462 100644
--- a/tests/namespace_test/NamespaceA/TableInFirstNS.java
+++ b/tests/namespace_test/NamespaceA/TableInFirstNS.java
@@ -10,15 +10,16 @@
 @SuppressWarnings("unused")
 public final class TableInFirstNS extends Table {
   public static TableInFirstNS getRootAsTableInFirstNS(ByteBuffer _bb) { return getRootAsTableInFirstNS(_bb, new TableInFirstNS()); }
-  public static TableInFirstNS getRootAsTableInFirstNS(ByteBuffer _bb, TableInFirstNS obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
-  public TableInFirstNS __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static TableInFirstNS getRootAsTableInFirstNS(ByteBuffer _bb, TableInFirstNS obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
+  public TableInFirstNS __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
   public NamespaceA.NamespaceB.TableInNestedNS fooTable() { return fooTable(new NamespaceA.NamespaceB.TableInNestedNS()); }
-  public NamespaceA.NamespaceB.TableInNestedNS fooTable(NamespaceA.NamespaceB.TableInNestedNS obj) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
+  public NamespaceA.NamespaceB.TableInNestedNS fooTable(NamespaceA.NamespaceB.TableInNestedNS obj) { int o = __offset(4); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; }
   public byte fooEnum() { int o = __offset(6); return o != 0 ? bb.get(o + bb_pos) : 0; }
   public boolean mutateFooEnum(byte foo_enum) { int o = __offset(6); if (o != 0) { bb.put(o + bb_pos, foo_enum); return true; } else { return false; } }
   public NamespaceA.NamespaceB.StructInNestedNS fooStruct() { return fooStruct(new NamespaceA.NamespaceB.StructInNestedNS()); }
-  public NamespaceA.NamespaceB.StructInNestedNS fooStruct(NamespaceA.NamespaceB.StructInNestedNS obj) { int o = __offset(8); return o != 0 ? obj.__init(o + bb_pos, bb) : null; }
+  public NamespaceA.NamespaceB.StructInNestedNS fooStruct(NamespaceA.NamespaceB.StructInNestedNS obj) { int o = __offset(8); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; }
 
   public static void startTableInFirstNS(FlatBufferBuilder builder) { builder.startObject(3); }
   public static void addFooTable(FlatBufferBuilder builder, int fooTableOffset) { builder.addOffset(0, fooTableOffset, 0); }
diff --git a/tests/namespace_test/NamespaceC/TableInC.cs b/tests/namespace_test/NamespaceC/TableInC.cs
index 0f75dfe..6dddcd4 100644
--- a/tests/namespace_test/NamespaceC/TableInC.cs
+++ b/tests/namespace_test/NamespaceC/TableInC.cs
@@ -6,15 +6,17 @@
 using System;
 using FlatBuffers;
 
-public sealed class TableInC : Table {
+public struct TableInC : IFlatbufferObject
+{
+  private Table __p;
+  public ByteBuffer ByteBuffer { get { return __p.bb; } }
   public static TableInC GetRootAsTableInC(ByteBuffer _bb) { return GetRootAsTableInC(_bb, new TableInC()); }
-  public static TableInC GetRootAsTableInC(ByteBuffer _bb, TableInC obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
-  public TableInC __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static TableInC GetRootAsTableInC(ByteBuffer _bb, TableInC obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
+  public TableInC __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
-  public NamespaceA.TableInFirstNS ReferToA1 { get { return GetReferToA1(new NamespaceA.TableInFirstNS()); } }
-  public NamespaceA.TableInFirstNS GetReferToA1(NamespaceA.TableInFirstNS obj) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
-  public SecondTableInA ReferToA2 { get { return GetReferToA2(new SecondTableInA()); } }
-  public SecondTableInA GetReferToA2(SecondTableInA obj) { int o = __offset(6); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
+  public NamespaceA.TableInFirstNS? ReferToA1 { get { int o = __p.__offset(4); return o != 0 ? (NamespaceA.TableInFirstNS?)(new NamespaceA.TableInFirstNS()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
+  public SecondTableInA? ReferToA2 { get { int o = __p.__offset(6); return o != 0 ? (SecondTableInA?)(new SecondTableInA()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
 
   public static Offset<NamespaceC.TableInC> CreateTableInC(FlatBufferBuilder builder,
       Offset<NamespaceA.TableInFirstNS> refer_to_a1Offset = default(Offset<NamespaceA.TableInFirstNS>),
diff --git a/tests/namespace_test/NamespaceC/TableInC.java b/tests/namespace_test/NamespaceC/TableInC.java
index 19bb4cd..12658ed 100644
--- a/tests/namespace_test/NamespaceC/TableInC.java
+++ b/tests/namespace_test/NamespaceC/TableInC.java
@@ -10,13 +10,14 @@
 @SuppressWarnings("unused")
 public final class TableInC extends Table {
   public static TableInC getRootAsTableInC(ByteBuffer _bb) { return getRootAsTableInC(_bb, new TableInC()); }
-  public static TableInC getRootAsTableInC(ByteBuffer _bb, TableInC obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
-  public TableInC __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+  public static TableInC getRootAsTableInC(ByteBuffer _bb, TableInC obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
+  public TableInC __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
 
   public NamespaceA.TableInFirstNS referToA1() { return referToA1(new NamespaceA.TableInFirstNS()); }
-  public NamespaceA.TableInFirstNS referToA1(NamespaceA.TableInFirstNS obj) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
+  public NamespaceA.TableInFirstNS referToA1(NamespaceA.TableInFirstNS obj) { int o = __offset(4); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; }
   public SecondTableInA referToA2() { return referToA2(new SecondTableInA()); }
-  public SecondTableInA referToA2(SecondTableInA obj) { int o = __offset(6); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
+  public SecondTableInA referToA2(SecondTableInA obj) { int o = __offset(6); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; }
 
   public static int createTableInC(FlatBufferBuilder builder,
       int refer_to_a1Offset,