'사용' 지시어는 C#에서 네임스페이스 내부에 있어야 합니까 아니면 외부에 있어야 합니까?
몇 가지 C# 코드에 대해 StyleCop을 실행했는데 계속해서 다음과 같이 보고됩니다.using
디렉티브는 네임스페이스 안에 있어야 합니다.
기술적인 이유가 있습니까?using
네임스페이스 외부 대신 내부에 있는 지시문?
그 둘 사이에는 사실 미묘한 차이가 있습니다.File1.cs 에 다음 코드가 있다고 가정해 보십시오.
// File1.cs
using System;
namespace Outer.Inner
{
class Foo
{
static void Bar()
{
double d = Math.PI;
}
}
}
이제 누군가가 다음과 같은 다른 파일(File2.cs )을 프로젝트에 추가한다고 상상해 보십시오.
// File2.cs
namespace Outer
{
class Math
{
}
}
는 컴일러검니다색합가를 합니다.Outer
그것들을 using
에 네스페이외있지찾수있을습다니를시를 찾습니다.Outer.Math
에 System.Math
( 운이 좋은 것일까요?),Outer.Math
이 없습니다.PI
멤버, 그래서 파일1은 이제 깨졌습니다.
이것은 다음과 같은 경우에 변경됩니다.using
다음과 같이 네임스페이스 선언 내부에 있습니다.
// File1b.cs
namespace Outer.Inner
{
using System;
class Foo
{
static void Bar()
{
double d = Math.PI;
}
}
}
는 이제컴러검니다합색가를 검색합니다.System
하기 전에Outer
, 편집System.Math
모든 것이 다 좋습니다.
라고 주장하는 사람도 있을 것입니다.Math
정의 클래스에는 이 있기 에 사용자 에는 좋지 않은 일 수 .System
여기서 요점은 단지 차이가 있다는 것이고, 그것은 코드의 유지보수성에 영향을 미친다는 것입니다.
만약에 어떤 일이 일어난다면 어떤 일이 벌어질지 주목하는 것도 흥미롭습니다.Foo
네임스페이스에 있습니다.Outer
에, 다는보는Outer.Inner
이경우, 가추를 합니다.Outer.Math
파일2에서 파일1은 위치에 상관없이 깨집니다.using
이는 컴파일러가 가장 안쪽에 있는 이름 공간을 먼저 검색한다는 것을 의미합니다.using
지시의
이 스레드에는 이미 몇 가지 훌륭한 답변이 있지만, 이 추가 답변을 통해 조금 더 자세히 설명할 수 있을 것 같습니다.
먼저, 다음과 같은 마침표가 있는 네임스페이스 선언을 기억하십시오.
namespace MyCorp.TheProduct.SomeModule.Utilities
{
...
}
는 완전히 다음과 같습니다.
namespace MyCorp
{
namespace TheProduct
{
namespace SomeModule
{
namespace Utilities
{
...
}
}
}
}
당신이 원한다면, 당신은 할 수 있습니다.using
이 모든 수준에 대한 지침입니다. (물론, 우리는 갖고 싶습니다.)using
는 한, 일 것입니다의 한곳에만가만지능하것서합따다입법, 라일적니언어에는)것▁s다입니일합법적▁according)따▁in▁bes▁legal,라▁would
어떤 유형이 암시되는지 확인하기 위한 규칙은 다음과 같이 대략적으로 설명할 수 있습니다.먼저 가장 안쪽의 "범위"에서 일치하는 항목을 검색하고, 아무 것도 발견되지 않으면 다음 범위로 한 수준을 이동하여 일치하는 항목이 발견될 때까지 검색합니다.특정 수준에서 일치하는 항목이 두 개 이상 발견되면 현재 어셈블리에서 일치하는 유형 중 하나가 있으면 해당 유형을 선택하고 컴파일러 경고를 발행합니다.그렇지 않으면 포기합니다(컴파일 시간 오류).
이제 두 개의 주요 협약에 대한 구체적인 예에서 이것이 무엇을 의미하는지 명시적으로 설명해 보겠습니다.
외부에서 사용하는 경우:
using System;
using System.Collections.Generic;
using System.Linq;
//using MyCorp.TheProduct; <-- uncommenting this would change nothing
using MyCorp.TheProduct.OtherModule;
using MyCorp.TheProduct.OtherModule.Integration;
using ThirdParty;
namespace MyCorp.TheProduct.SomeModule.Utilities
{
class C
{
Ambiguous a;
}
}
위의 경우, 어떤 유형인지 알아보기 위해Ambiguous
은 다음됩니다.
- 에 중유형 안에
C
유형 상속 된중유포함형첩)포상 - 네임스페이스에 입니다.
MyCorp.TheProduct.SomeModule.Utilities
- 의
MyCorp.TheProduct.SomeModule
- 의
MyCorp.TheProduct
- 의
MyCorp
- null 네임스페이스(글로벌 네임스페이스)의 유형
- 의
System
,System.Collections.Generic
,System.Linq
,MyCorp.TheProduct.OtherModule
,MyCorp.TheProduct.OtherModule.Integration
,그리고.ThirdParty
다른 관례:
내부에서 사용할 경우:
namespace MyCorp.TheProduct.SomeModule.Utilities
{
using System;
using System.Collections.Generic;
using System.Linq;
using MyCorp.TheProduct; // MyCorp can be left out; this using is NOT redundant
using MyCorp.TheProduct.OtherModule; // MyCorp.TheProduct can be left out
using MyCorp.TheProduct.OtherModule.Integration; // MyCorp.TheProduct can be left out
using ThirdParty;
class C
{
Ambiguous a;
}
}
이제 해 보세요.Ambiguous
다음 순서로 진행됩니다.
- 에 중유형 안에
C
유형 상속 된중유포함형첩)포상 - 네임스페이스에 입니다.
MyCorp.TheProduct.SomeModule.Utilities
- 의
System
,System.Collections.Generic
,System.Linq
,MyCorp.TheProduct
,MyCorp.TheProduct.OtherModule
,MyCorp.TheProduct.OtherModule.Integration
,그리고.ThirdParty
- 의
MyCorp.TheProduct.SomeModule
- 의
MyCorp
- null 네임스페이스(글로벌 네임스페이스)의 유형
:MyCorp.TheProduct
는 "에 " 사이에."3."4."4."5." 이사필않니다았습 5.")
끝맺음
사용자가 네임스페이스 선언 내부 또는 외부에 위치하더라도 나중에 다른 사용자가 동일한 이름을 가진 새 유형을 우선 순위가 높은 네임스페이스 중 하나에 추가할 가능성이 항상 있습니다.
또한 중첩된 네임스페이스의 이름이 유형과 동일한 경우 문제가 발생할 수 있습니다.
검색 계층이 변경되고 다른 유형이 발견될 수 있기 때문에 한 위치에서 다른 위치로 사용을 이동하는 것은 항상 위험합니다.따라서 사용법을 이동할 필요가 없도록 하나의 규칙을 선택하고 이를 고수하십시오.
Visual Studio의 템플릿은 기본적으로 사용자를 네임스페이스 외부에 배치합니다(예: VS가 새 파일에 새 클래스를 생성하도록 하는 경우).
외부에서 사용할 경우의 한 가지(작은) 이점은 글로벌 속성에 대한 지시어 사용을 활용할 수 있다는 것입니다.[assembly: ComVisible(false)]
에 [assembly: System.Runtime.InteropServices.ComVisible(false)]
.
파일 범위 네임스페이스 선언 업데이트
C# 10.0 이후(2021년부터) 들여쓰기를 방지하고 다음 중 하나를 사용할 수 있습니다(컨벤션 1, 외부 사용).
using System;
using System.Collections.Generic;
using System.Linq;
using MyCorp.TheProduct.OtherModule;
using MyCorp.TheProduct.OtherModule.Integration;
using ThirdParty;
namespace MyCorp.TheProduct.SomeModule.Utilities;
class C
{
Ambiguous a;
}
또는 (컨벤션 2, 내부 사용):
namespace MyCorp.TheProduct.SomeModule.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using MyCorp.TheProduct;
using MyCorp.TheProduct.OtherModule;
using MyCorp.TheProduct.OtherModule.Integration;
using ThirdParty;
class C
{
Ambiguous a;
}
그러나 이전과 같은 고려사항이 적용됩니다.
네임스페이스 안에 넣으면 파일에 대한 해당 네임스페이스에 대한 로컬 선언이 되지만(파일에 여러 네임스페이스가 있는 경우), 파일당 하나의 네임스페이스만 있는 경우 네임스페이스가 네임스페이스 외부로 이동하든 내부로 이동하든 큰 차이가 없습니다.
using ThisNamespace.IsImported.InAllNamespaces.Here;
namespace Namespace1
{
using ThisNamespace.IsImported.InNamespace1.AndNamespace2;
namespace Namespace2
{
using ThisNamespace.IsImported.InJustNamespace2;
}
}
namespace Namespace3
{
using ThisNamespace.IsImported.InJustNamespace3;
}
Hanselman에 따르면 - 지침 및 어셈블리 로딩 사용...그리고 다른 그런 기사들은 기술적으로 차이가 없습니다.
제가 선호하는 것은 이름 공간 밖에 두는 것입니다.
StyleCop 설명서에 따름:
SA1200: 지침 사용은 네임스페이스 내에 배치해야 합니다.
지시문을 사용하는 C#이 네임스페이스 요소 외부에 배치되었기 때문입니다.
규칙 설명 파일에 네임스페이스 요소가 없는 경우를 제외하고 사용 지침 또는 사용 별칭 지침을 네임스페이스 요소 외부에 배치하면 이 규칙을 위반할 수 있습니다.
예를 들어, 다음 코드는 이 규칙을 두 번 위반하게 됩니다.
using System;
using Guid = System.Guid;
namespace Microsoft.Sample
{
public class Program
{
}
}
그러나 다음 코드는 이 규칙을 위반하지 않습니다.
namespace Microsoft.Sample
{
using System;
using Guid = System.Guid;
public class Program
{
}
}
이 코드는 컴파일러 오류 없이 깨끗하게 컴파일됩니다.그러나 GUID 유형의 어떤 버전이 할당되고 있는지는 불분명합니다.아래와 같이 사용 지침이 네임스페이스 내부로 이동하면 컴파일러 오류가 발생합니다.
namespace Microsoft.Sample
{
using Guid = System.Guid;
public class Guid
{
public Guid(string s)
{
}
}
public class Program
{
public static void Main(string[] args)
{
Guid g = new Guid("hello");
}
}
}
는 다음 합니다. 이는 다음컴코실다패니드합가가 포함된 되었습니다. 다음을 포함하는 줄에 있습니다.Guid g = new Guid("hello");
CS0576: 네임스페이스 'Microsoft.sample'에 별칭 'Guid'와 충돌하는 정의가 포함되어 있습니다.
코드는 시스템에 대한 별칭을 만듭니다.GUID라는 GUID 유형과 일치하는 생성자 인터페이스를 사용하여 GUID라는 자체 유형을 만듭니다.나중에 코드는 Guid 유형의 인스턴스를 만듭니다.이 인스턴스를 만들려면 컴파일러가 GUID의 두 가지 다른 정의 중 하나를 선택해야 합니다.using-alias 지시어가 네임스페이스 요소 외부에 배치되면 컴파일러는 로컬 네임스페이스 내에 정의된 GUID의 로컬 정의를 선택하고 네임스페이스 외부에 정의된 using-alias 지시어를 완전히 무시합니다.안타깝게도, 이것은 코드를 읽을 때 명확하지 않습니다.
그러나 using-alias 지시어가 네임스페이스 내에 위치할 경우 컴파일러는 동일한 네임스페이스 내에 정의된 서로 다른 두 개의 충돌하는 GUID 유형 중에서 선택해야 합니다.두 유형 모두 일치하는 생성자를 제공합니다.컴파일러가 결정을 내릴 수 없으므로 컴파일러 오류에 플래그를 지정합니다.
using-alias 지시어를 네임스페이스 외부에 배치하는 것은 실제로 사용 중인 유형의 버전이 명확하지 않은 경우와 같은 상황에서 혼동을 일으킬 수 있기 때문에 좋지 않은 방법입니다.이로 인해 잠재적으로 진단하기 어려울 수 있는 버그가 발생할 수 있습니다.
using-alias 지시어를 네임스페이스 요소 내에 배치하면 버그의 원인이 되지 않습니다.
- 다중 네임스페이스
일반적으로 하나의 파일에 여러 네임스페이스 요소를 배치하는 것은 좋지 않지만, 이 작업을 수행할 때는 파일의 맨 위에 전체적으로 배치하는 것이 아니라 각 네임스페이스 요소 내에 모든 사용자 지시어를 배치하는 것이 좋습니다.이렇게 하면 네임스페이스의 범위가 엄격해지고 위에서 설명한 동작을 방지할 수 있습니다.
네임스페이스 외부에 배치된 디렉티브를 사용하여 코드를 작성한 경우 네임스페이스 내에서 이러한 디렉티브를 이동할 때 코드의 의미가 변경되지 않도록 주의해야 합니다.위에서 설명한 대로 using-alias 지시어를 네임스페이스 요소 내에 배치하면 컴파일러가 네임스페이스 외부에 배치할 때 발생하지 않는 방법으로 충돌하는 유형을 선택할 수 있습니다.
위반을 수정하는 방법 이 규칙의 위반을 수정하려면 네임스페이스 요소 내에서 디렉티브 및 using-alias 디렉티브를 사용하여 모두 이동합니다.
별칭을 사용하려는 경우 네임스페이스 내에 문을 사용하여 배치하는 데 문제가 있습니다.별칭은 이전의 별칭으로부터 이익을 얻지 못합니다.using
완전한 자격을 갖추어야 합니다.
고려 사항:
namespace MyNamespace
{
using System;
using MyAlias = System.DateTime;
class MyClass
{
}
}
대:
using System;
namespace MyNamespace
{
using MyAlias = DateTime;
class MyClass
{
}
}
이는 다음과 같은 장황한 별칭이 있는 경우 특히 두드러질 수 있습니다(문제를 통해 문제를 발견했습니다).
using MyAlias = Tuple<Expression<Func<DateTime, object>>, Expression<Func<TimeSpan, object>>>;
와 함께using
네임스페이스 내의 문은 갑자기 다음과 같이 됩니다.
using MyAlias = System.Tuple<System.Linq.Expressions.Expression<System.Func<System.DateTime, object>>, System.Linq.Expressions.Expression<System.Func<System.TimeSpan, object>>>;
안이쁘다.
우연히 마주친 한 가지 주름(다른 답변에서는 다루지 않음):
다음과 같은 네임스페이스가 있다고 가정합니다.
- 뭔가.다른.
- 부모님, 뭔가.다른.
를 할 때using Something.Other
의 외부에namespace Parent
그것은 첫 번째 것(Something)을 가리킵니다.
그러나 해당 네임스페이스 선언 내에서 사용하는 경우 두 번째 네임스페이스 선언(부모)을 참조합니다.뭔가.기타)!
해결책이 : " 단한해이있다를니습오시 " 추가하십간결책오▁"▁the시십▁"를▁there"를 추가하세요.global::
접두사: 문서
namespace Parent
{
using global::Something.Other;
// etc
}
다른 답변에서 다루지 않았다고 생각되는 또 다른 미묘한 점은 같은 이름의 클래스와 네임스페이스가 있는 경우입니다.
네임스페이스 내에 가져오기가 있으면 클래스를 찾습니다.가져오기가 네임스페이스 외부에 있으면 가져오기가 무시되고 클래스 및 네임스페이스가 완전히 검증되어야 합니다.
//file1.cs
namespace Foo
{
class Foo
{
}
}
//file2.cs
namespace ConsoleApp3
{
using Foo;
class Program
{
static void Main(string[] args)
{
//This will allow you to use the class
Foo test = new Foo();
}
}
}
//file3.cs
using Foo; //Unused and redundant
namespace Bar
{
class Bar
{
Bar()
{
Foo.Foo test = new Foo.Foo();
Foo test = new Foo(); //will give you an error that a namespace is being used like a class.
}
}
}
Jepp Stig Nielsen이 말했듯이, 이 스레드는 이미 훌륭한 답변을 가지고 있지만, 저는 이 다소 명백한 미묘함도 언급할 가치가 있다고 생각했습니다.
using
네임스페이스 내부에 지정된 지시어는 외부에 지정될 때처럼 완전한 인증을 받을 필요가 없기 때문에 더 짧은 코드를 만들 수 있습니다.
는 유형이 " 다예제다유때작다동니합에문"이기합니다.Foo
그리고.Bar
다 동일한 인 둘다동글네로있습에니다임에 있습니다.Outer
.
코드 파일 Foo.cs 을 가정합니다.
namespace Outer.Inner
{
class Foo { }
}
그리고 Bar.cs :
namespace Outer
{
using Outer.Inner;
class Bar
{
public Foo foo;
}
}
그러면 의 외부 네임스페이스가 생략될 수 있습니다.using
, 지시줄, 여말하면서:
namespace Outer
{
using Inner;
class Bar
{
public Foo foo;
}
}
기술적인 이유는 답변에서 논의되었고 차이가 크지 않고 두 가지 모두 트레이드오프가 있기 때문에 결국 개인적인 선호도로 온다고 생각합니다.Visual Studio의 생성 기본 템플릿.cs
은 파사용을 합니다.using
네임스페이스 외부의 지시어(예:
스타일 경찰을 조정하여 확인할 수 있습니다.using
추가를 stylecop.json
프로젝트 파일의 루트에 다음과 같은 파일이 있습니다.
{
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
"orderingRules": {
"usingDirectivesPlacement": "outsideNamespace"
}
}
}
솔루션 수준에서 이 구성 파일을 만들고 프로젝트에 '기존 링크 파일'로 추가하여 모든 프로젝트에서 구성을 공유할 수 있습니다.
아직 언급되지 않음:
를 하는 중using
네임스페이스 선언 내부의 디렉티브는 가능한 한 가장 작은 범위에서 모든 것을 선언하는 잘 알려진 최고의 프로그래밍 관행의 응용 프로그램입니다.
최상의 프로그래밍 방식이 제2의 천성이라면 자동으로 그런 작업을 수행할 수 있습니다.
이것이 다른 곳에서 언급된 (경계선) 기술적 (경계선) 장점과 상관없이 사용 지침을 네임스페이스 선언 안에 넣는 가장 좋은 이유일 수 있습니다. 이것은 매우 간단합니다.
이미 언급되었지만 더 잘 설명되어 있을 수 있습니다.
치를 using
네임스페이스 내부의 지시어는 불필요한 반복을 방지하고 선언문을 더 간결하게 만듭니다.
이것은 불필요하게 간결합니다.
using Com.Acme.Products.Traps.RoadRunnerTraps;
namespace Com.Acme.Products.Traps {
이것은 달콤하고 요점을 말해줍니다.
namespace Com.Acme.Products.Traps {
using RoadRunnerTraps;
외부는using
명령어(예: 시스템 및 마이크로소프트 네임스페이스)는 외부에 배치되어야 합니다.namespace
지시의별도로 지정하지 않는 한 모든 경우에 적용해야 하는 기본값입니다.여기에는 현재 프로젝트에 포함되지 않은 조직의 내부 라이브러리가 포함되어야 합니다.using
동일한 프로젝트의 다른 기본 네임스페이스를 참조하는 명령어입니다.조금도using
현재 프로젝트 및 네임스페이스의 다른 모듈을 참조하는 지침은 내부에 배치되어야 합니다.namespace
은 두 기능을 합니다: 이 기 은 가 특 기 제 공 합 니 다 을 능 정 지 시 두 의 능 지 다 : 니 제 ▁two 합 ▁specific공 ▁functions
- 로컬 모듈과 '기타' 모듈을 시각적으로 구분합니다. 다른 모든 것을 의미합니다.
- 현지 지침이 글로벌 지침보다 우선적으로 적용될 수 있도록 범위를 지정합니다.
후자의 이유는 중요합니다.코드 리팩터링보다 중요하지 않은 변경으로 인해 도입될 수 있는 모호한 참조 문제를 도입하는 것이 더 어렵다는 것을 의미합니다.즉, 한 파일에서 다른 파일로 메서드를 이동하면 이전에는 없었던 버그가 갑자기 나타납니다.구어적으로 '하이젠버그' - 역사적으로 추적하기가 매우 어렵습니다.
대부분의 답변은 배치에 치우칩니다.using
부내지의 내부 namespace
C# 코딩 규약에서 마이크로소프트의 권장 사항이 달리 언급되어 있다는 것은 흥미로운 사실입니다.
사용 중인 지시어를 네임스페이스 선언 외부에 배치합니다.
사용 지시어가 네임스페이스 선언 외부에 있는 경우 가져온 네임스페이스는 정규화된 이름입니다.그게 더 확실해요.사용 지침이 네임스페이스 내부에 있는 경우 해당 네임스페이스에 상대적이거나 정규화된 이름일 수 있습니다.애매하네요.
그러나 이 다른 게시물에서는 그 반대를 규정합니다.
문은 네임스페이스 선언 안에 있어야 합니다.
기본적으로 다음과 같은 방법을 사용하는 것이 좋습니다.소스 솔루션에 사용되는 "차이"는 네임스페이스 외부에 있어야 하며 "새로 추가된 참조"는 네임스페이스 내부에 두는 것이 좋습니다.추가되는 참조를 구분하기 위한 것입니다.
언급URL : https://stackoverflow.com/questions/125319/should-using-directives-be-inside-or-outside-the-namespace-in-c
'programing' 카테고리의 다른 글
잘못된 Swift 지원 - 파일이 일치하지 않습니다. (0) | 2023.05.02 |
---|---|
RouterModule.for 루트(ROUTES) vs RouterModule.어린이용(ROUTS) (0) | 2023.05.02 |
여러 개의 키로 "구별"을 효율적으로 수행하는 방법은 무엇입니까? (0) | 2023.05.02 |
중첩된 딕트의 Python 데이터 클래스 (0) | 2023.05.02 |
Excel에서 GUID를 만드는 방법은 무엇입니까? (0) | 2023.05.02 |