Is it possible to define an assembly-wide using SomeNamespace statement in C#, such that all classes and code files in that assembly include that namespace without having to specify using SomeNamespace?
Considering I can't find it in the MSDN documentation and haven't ran into it in the past 6 years of writing C#, I'm doubtful but figured I'd ask others anyway.
using doesn't exist in assemblies, or in the produced code.
It is a shorthand that only exists in the source code.
Consider the classic "Hello World":
using System;
namespace Hello
{
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
The actual bytecode of the Main method produced would be expressed as CIL assembly as:
ldstr "Hello World!"
call void [mscorlib]System.Console::WriteLine(string)
ret
Note that this is exactly the same as if we left the using System out of the C# source file, and used System.Console.WriteLine() instead. Indeed, it's even a bit more wordy than that, since the method signature used in the actual produced code includes the assembly as ([mscorlib]).
To speak of an "assembly-wide using SomeNamespace" is meaningless, as assemblies don't have any using at all.
Since using directives are something that is in a source file, rather than in an assembly, it's a source problem, not an assembly problem. Edit the templates your IDE uses to include those statements you need, or use one that adds using statements when it can only find matching intellisense suggestions by looking outside of the possible suggestions based on the current using directives for the file.
Related
I've got an issue when importing a package/library that introduces namespace Math.Native.Gmp (it's called "Math.Gmp.Native" on NuGet).
Before import, this code works perfectly fine:
using System;
namespace Sample
{
public int Foo()
{
return Math.Min(1, 2);
}
}
After adding this reference, however, Math is no longer recognized as a System.Math, but is hidden by the newly added namespace - Math. expects only Math.Native as the correct extension of the path.
Trying to use Math.Min ends up with compiler error:
[CS0234] The type or namespace name 'Min' does not exist in the namespace 'Math' (are you missing an assembly reference?)
I found out that original Math is still accessible via System.Math, so in the example above, after adding this prefix (return System.Math.Min(1, 2);) everything works as intended. It is some walkaround
My question is - how to avoid that overshadowing of Math? Can I use some using commands at the beginning of the file to avoid it?. Can I make some alias for Math.Native.Gmp namespace so that it won't be conflicting with System.Math?
As described in the documentation of the using statement you can use something like
using myMath = System.Math;
to define an alias for a namespace.
There IS a way to resolve this conflict by moving Math.Gmp.Native namespace away. That can be done by setting an alias to that library. In .csproj file of our project set ("Gmp" is just a selected name by me):
<PackageReference Include="Math.Gmp.Native.NET">
<Aliases>Gmp</Aliases>
</PackageReference>
In that way Math.<xyz> no longer means things from that library, but - as intended - from System.Math.
In files where you want to use the imported library, you have to include:
extern alias Gmp;
using Gmp::Math.Gmp.Native;
It won't create conflicts either!
HUGE WARNING: This solution has a massive drawback. When you want to use this project in your second project, the second project will have exactly the same issue. Although Math.Gmp.Native.NET is a just nested reference, it causes the same overshadowing of the Math namespace.
So, in every project using Math.Gmp.Native.NET anywhere in a tree of references, Math is overshadowed by the library's one. If you want to use Math there as the default System.Math, you got to include in its .csproj same code shown above.
It gets messy and hard to follow why Math doesn't work without that magic reference in the .csproj file in the project not even using (directly) anything from this library. That is why I haven't chosen this answer as an accepted one
To build up on alrady given answer:
whenever you have this conflict, System.Math was there first. So to make things working again use in every file using statement:
using Math = System.Math;
If you want to use the other namespace easily, you can rely here on #MarkusSafar answer and use some custom alias:
using OtherMath = /*other math namespace*/;
or just use fully qualified names.
I discovered this quite by accident, but I had apparently written some incorrect code in a much larger project. I've reduced it to an MVCE, and am curious why it even compiles. I accidentally added what the system appears to be treating as a variable name after a type check in C#, and it appears to be treating as an alias to the variable I was type checking. You can test in the dotnetfiddle below.
Does anyone have an explanation for what on earth is going on here?
For reference I'm using vs2017 enterprise with a .net 4.6.1 project.
using System;
public class Program
{
public static void Main()
{
string foo = "hello world";
if (!(foo is string str)) { return; }
Console.WriteLine(str);
}
}
https://dotnetfiddle.net/BwT1kx
Not a bug, but a feature! that's the pattern matching supported by the is keyword since C# 7.0
For some reason, your IDE is using the wrong C# version for analysing the code and giving you incorrect squiggly lines.
This is a feature called pattern matching as others pointed starting from C#. If you are interested in what compiler translates this to you can check compiler generated code.
Notice how in Release mode compiler makes static analysis that foo is always a string type and omits most of the generated code in Debug.
Is there any way to check if unity library exists in the project with scripts.
For example:
using UnityEngine.Advertisements;
And if it exists then make some actions like:
Advertisements.IsReady();
Thank you for your help!
Have a look at the MSDN documentation about the method Assembly.GetReferencedAssemblies(). This method returns an AssemblyName[] containing the names for all the assemblies referenced by this assembly. In other words the referenced assemblies are e.g. a library. Then you can easily wrap your a code in an if statement to either execute the code if your desired library (name) is contained in the array or to not execute.
Sample code:
Assembly currentAssembly = typeof(/*enter the class name which contains the assembly references*/).Assembly;
AssemblyName[] referencedAssemblies = currentAssembly.GetReferencedAssemblies();
foreach (var refAssembly in referencedAssemblies)
{
if (assembly == /*the name of the assembly you want to check that has to exist*/)
{
//...do your work if the assembly exists
break;
}
}
The technique behind this is called Reflection which I can highly recommend you to read about, its quite interesting.
You cannot use if else statement in this case because the compiler will complain about this, for example if(false) Advertisements.IsReady(); compiler cannot find type Advertisements.
But theres another way, you can use Reflection to get Type from the assembly. and then get the method to call, but still this is not the practical way.
You may want to use constant instead, or use ClassAttribute to tell that this script enable for advertisements, but using UnityEngine.Advertisements; is a must, you can create custom monobehaviour for this, and then inherit it to your application so that you can hide this line using UnityEngine.Advertisements;
I tried the following
// no using statements here, not even using System;
class Program
{
static void Main(string[] args)
{
string[] arr = new string[3] { "A" , "B", "C" };
}
}
My question is simple, even without any using statements, how come compiler is able to compile this, more specifically, shouldn't there be a compile time error because I am trying to build an array and System.Array is not accessible?
Thanks.
You seem to have a misunderstanding about what using means. A using directive is for determining what a simple name means in your program at compile time. When you say using Foo; that means "if the text of this program uses the simple name Bar, and it doesn't seem like anything named Bar is in scope where the name is used then try checking to see if there is a type called Bar inside namespace Foo".
Your program does not contain any simple names! (string is not a simple name; it is a keyword of the language.) Therefore there is no need to have any using directive to resolve the non-existing simple names.
using does not at all mean "this program uses features that require types found in this assembly", which is what you seem to think it means. using directives are only about (1) simple name resolution, and (2) extension method name resolution.
Arrays are part of the language. You don't need to reference a namespace to use them.
string[] will translate to System.Array while compiling. Since its already fully qualified, it doesn't need any using statements.
You're not referring by name to any namespaced type but yours (the Program class).
string and [] are aliases that are indeed equivalent to System.String and System.Array respectively, but using them does not require pulling their counterparts' namespaces into scope.
You aren't directly referencing the Array class or its members, so the compiler won't complain that you're trying to reference an unused namespace or type. You're just using notation that's part of the C# language itself to make arrays.
This is because you are using core things, you don't even need System for this to compile. The System namespace has extended functionality, some of the classes included in the System Namespace is:
Action
Func
Console
And many more..
As you are not trying to write something to the command prompt, creating actions or even asking for date using DateTime, you don't need to import anything.
using statements do not include anything or provide any ekstra code. It only makes it simplier to code, because you don't have to write the whole path every time.
string automatically converts to System.String.
You can write this:
class Foo {
string Bar() {
return System.IO.File.Exists("path").ToString();
}
}
or just
using System.IO;
class Foo {
string Bar() {
return File.Exists("path").ToString();
}
}
both compiles to the same program.
Namespaces are not necessary, you can organize with namespaces your code but you don't have to.
And common keywords are automatically referenced to the proper namespace.
For better understanding read this msdna document http://msdn.microsoft.com/en-us/library/ms973231.aspx
I want to write a code generator and save these codes with mvp pattern, can I use Reflection.Emit as a solution or CodeDom is better?
EDIT--------------
I have to do 2 work, firstly I want to compile this code at runtime and run it and secondly generate the source code as an option.
Although you can achieve some aspects of your question with both Namespaces (System.CodeDom and System.Reflection.Emit) you can't mix the two different concepts and use the option(s) that better fits whatever you want to do.
If you just want to generate and compile C#\VB code maybe you want do use System.CodeDom:
This namespace can be used to model
the structure of a source code
document that can be output as source
code in a supported language using the
functionality provided by the
System.CodeDom.Compiler namespace.
Check this small example on how to define a method through CodeDom:
// Defines a method that returns a string passed to it.
CodeMemberMethod method1 = new CodeMemberMethod();
method1.Name = "ReturnString";
method1.ReturnType = new CodeTypeReference("System.String");
method1.Parameters.Add( new CodeParameterDeclarationExpression("System.String", "text") );
method1.Statements.Add( new CodeMethodReturnStatement( new CodeArgumentReferenceExpression("text") ) );
// A C# code generator produces the following source code for the preceeding example code:
// private string ReturnString(string text)
// {
// return text;
// }
As for the System.Reflection.Emit its used to generate and manipulate MSIL (Microsoft Intermediate Language) which is lowest-level human-readable programming language defined by the Common Language Infrastructure specification and used by the .NET Framework. Note that MSIL is now known as CIL (Common Intermediate Language):
The System.Reflection.Emit namespace
contains classes that allow a compiler
or tool to emit metadata and Microsoft
intermediate language (MSIL) and
optionally generate a PE file on disk.
The primary clients of these classes
are script engines and compilers.
The use of this approach leads you to learn CIL bytecode instructions which is a rather difficult and complex task even if you're familiar with assembly code and might not be ideal if what you want is rather simple and fast to implement. Check wikipedia article on CIL and CIL instructions list for a first impression.
If you're going to want the option to see the C# source code, I say go with CodeDom. Reflection.Emit renders IL, but getting that to usable C# code is not going to be easy.