if 문의 할당
클래스 Animal
와 하위 클래스가 Dog
있습니다. 나는 종종 다음 줄을 코딩하는 것을 발견했다.
if (animal is Dog)
{
Dog dog = animal as Dog;
dog.Name;
...
}
변수의 경우 Animal animal;
.
다음과 같은 것을 작성할 수있는 구문이 있습니까?
if (Dog dog = animal as Dog)
{
dog.Name;
...
}
아래 답변은 몇 년 전에 작성되었으며 시간이 지남에 따라 업데이트되었습니다. C # 7부터 패턴 일치를 사용할 수 있습니다.
if (animal is Dog dog)
{
// Use dog here
}
주의 dog
애프터 범위에 여전히 if
문,하지만 확실히 할당되지 않습니다.
아닙니다. 이것을 작성하는 것이 관용적입니다.
Dog dog = animal as Dog;
if (dog != null)
{
// Use dog
}
"다음에 if"가 거의 항상 이런 식으로 사용 된다는 것을 감안할 때 , 한 번에 두 부분을 모두 수행하는 연산자가있는 것이 더 합리적 일 수 있습니다. 패턴 일치 제안 이 구현 된 경우 현재 C # 6에는 없지만 C # 7에 포함될 수 있습니다 .
문제는 명령문 1 의 조건 부분에서 변수를 선언 할 수 없다는 것 입니다. 내가 생각할 수있는 가장 가까운 접근법은 다음과 같습니다.if
// EVIL EVIL EVIL. DO NOT USE.
for (Dog dog = animal as Dog; dog != null; dog = null)
{
...
}
그것은 단지 불쾌합니다 ... (방금 시도했지만 작동합니다. 그러나 제발, 제발, 제발 그렇게하지 마십시오. 아, 물론 dog
사용하여 선언 할 수 있습니다 var
.)
물론 확장 방법을 작성할 수 있습니다.
public static void AsIf<T>(this object value, Action<T> action) where T : class
{
T t = value as T;
if (t != null)
{
action(t);
}
}
그런 다음 전화하십시오.
animal.AsIf<Dog>(dog => {
// Use dog in here
});
또는 두 가지를 결합 할 수 있습니다.
public static void AsIf<T>(this object value, Action<T> action) where T : class
{
// EVIL EVIL EVIL
for (var t = value as T; t != null; t = null)
{
action(t);
}
}
for 루프보다 깔끔한 방식으로 람다식이없는 확장 메서드를 사용할 수도 있습니다.
public static IEnumerable<T> AsOrEmpty(this object value)
{
T t = value as T;
if (t != null)
{
yield return t;
}
}
그때:
foreach (Dog dog in animal.AsOrEmpty<Dog>())
{
// use dog
}
1 드물지만 문장에 값을 할당 할 수 있습니다 if
. 그러나 변수 선언과는 다릅니다. 데이터 스트림을 읽을 때 가끔 그렇게하는 것은 끔찍한 일 이 아닙니다 while
. 예를 들면 다음과 같습니다.
string line;
while ((line = reader.ReadLine()) != null)
{
...
}
요즘에는 일반적으로 래퍼를 사용하여 사용할 수 foreach (string line in ...)
있지만 위의 내용을 꽤 관용적 인 패턴으로 생각합니다. 그것은이다 일반적으로 조건 내에서 부작용을 가지고 좋은 아니지만, 대안은 일반적으로 코드 중복을 포함, 당신은이 패턴을 알고있을 때 그것을 바로 얻을 쉽습니다.
경우 as
에 실패, 그것은 반환합니다 null
.
Dog dog = animal as Dog;
if (dog != null)
{
// do stuff
}
변수가 이미 존재하는 한 변수에 값을 지정할 수 있습니다 . 문제가있는 경우 나중에 같은 방법으로 해당 변수 이름을 나중에 다시 사용할 수 있도록 변수의 범위를 지정할 수도 있습니다.
public void Test()
{
var animals = new Animal[] { new Dog(), new Duck() };
foreach (var animal in animals)
{
{ // <-- scopes the existence of critter to this block
Dog critter;
if (null != (critter = animal as Dog))
{
critter.Name = "Scopey";
// ...
}
}
{
Duck critter;
if (null != (critter = animal as Duck))
{
critter.Fly();
// ...
}
}
}
}
가정
public class Animal
{
}
public class Dog : Animal
{
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
Console.WriteLine("Name is now " + _name);
}
}
}
public class Duck : Animal
{
public void Fly()
{
Console.WriteLine("Flying");
}
}
출력을 얻는다 :
Name is now Scopey
Flying
테스트에서 변수 할당 패턴은 또한 스트림에서 바이트 블록을 읽을 때 사용됩니다.
int bytesRead = 0;
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
{
// ...
}
그러나 위에서 사용 된 변수 범위 패턴은 특히 일반적인 코드 패턴이 아니며, 모든 곳에서 사용되는 것을 보았을 때 리팩토링 할 방법을 찾고있었습니다.
다음과 같은 것을 작성할 수있는 구문이 있습니까?
if (Dog dog = animal as Dog) { ... dog ... }
?
C # 6.0에있을 것입니다. 이 기능을 "선언 표현식"이라고합니다. 보다
https://roslyn.codeplex.com/discussions/565640
자세한 내용은.
제안 된 구문은 다음과 같습니다.
if ((var i = o as int?) != null) { … i … }
else if ((var s = o as string) != null) { … s … }
else if ...
보다 일반적으로, 제안 된 특징은 로컬 변수 선언이 표현식으로 사용될 수 있다는 것 입니다. 이 if
구문은보다 일반적인 기능의 좋은 결과 일뿐입니다.
내가 자주 쓰고 사용하는 확장 방법 중 하나는 *
public static TResult IfNotNull<T,TResult>(this T obj, Func<T,TResult> func)
{
if(obj != null)
{
return func(obj);
}
return default(TResult);
}
이 상황에서 사용할 수있는 것은
string name = (animal as Dog).IfNotNull(x => x.Name);
그리고 개의 name
이름입니다 (개인 경우). 그렇지 않으면 null입니다.
* 이것이 성능 적인지 모르겠습니다. 프로파일 링에서 병목 현상이 발생하지 않았습니다.
여기서 곡식에 반대하지만 처음에 잘못하고있을 수 있습니다. 객체의 유형을 확인하는 것은 거의 항상 코드 냄새입니다. 귀하의 예에서 모든 동물이 이름을 가지고 있지는 않습니까? 그런 다음 개인 지 여부를 확인하지 않고 Animal.name을 호출하십시오.
또는 Animal의 구체적인 유형에 따라 다르게 작동하는 Animal 메서드를 호출하도록 메서드를 반전시킵니다. 참조 : 다형성.
짧은 진술
var dog = animal as Dog
if(dog != null) dog.Name ...;
다음은 기본 클래스 수정에 의존하는 더티 코드 (Jon 's와 같은 더티가 아님)입니다. 나는 그것이 요점을 누락시키면서 의도를 포착한다고 생각합니다.
class Animal
{
public Animal() { Name = "animal"; }
public List<Animal> IfIs<T>()
{
if(this is T)
return new List<Animal>{this};
else
return new List<Animal>();
}
public string Name;
}
class Dog : Animal
{
public Dog() { Name = "dog"; }
public string Bark { get { return "ruff"; } }
}
class Program
{
static void Main(string[] args)
{
var animal = new Animal();
foreach(Dog dog in animal.IfIs<Dog>())
{
Console.WriteLine(dog.Name);
Console.WriteLine(dog.Bark);
}
Console.ReadLine();
}
}
여러 개의 if-if를 하나씩 차례로 수행해야하는 경우 (다형성을 사용하는 것은 옵션이 아님) SwitchOnType 구문을 사용하십시오 .
C #의 대입 연산자가 유효한 식이므로 문제 (구문 사용)가 대입과 관련 이 없습니다 . 오히려 선언이 진술이므로 원하는 선언이 있습니다.
그런 코드를 작성 해야하는 경우 때로는 더 큰 컨텍스트에 따라 다음과 같이 코드를 작성합니다.
Dog dog;
if ((dog = animal as Dog) != null) {
// use dog
}
위의 구문 (요청한 구문에 가까운)에는 다음과 같은 장점이 있습니다.
dog
외부 에서 사용하면if
다른 곳에 값이 할당되지 않으므로 컴파일 오류가 발생합니다. (즉, 다른 곳에 할당 하지 마십시오dog
.)- 이 접근법은
if/else if/...
다음과 같이 훌륭하게 확장 될 수 있습니다 (as
적절한 지점을 선택하는 데 필요한만큼만 있습니다. 필요할 때이 양식으로 작성 하는 큰 경우 입니다). - 의 중복을 피하십시오
is/as
. (그러나Dog dog = ...
양식으로 도 수행됩니다 .) - "아이디 오마 틱 동안"과 다르지 않습니다. (단지 수행하지 마십시오. 조건을 일관된 형태로 단순하게 유지하십시오.)
dog
다른 세계와 진정으로 분리하기 위해 새로운 블록을 사용할 수 있습니다.
{
Dog dog = ...; // or assign in `if` as per above
}
Bite(dog); // oops! can't access dog from above
행복한 코딩.
확장 방법을 가진 또 다른 EVIL 솔루션 :)
public class Tester
{
public static void Test()
{
Animal a = new Animal();
//nothing is printed
foreach (Dog d in a.Each<Dog>())
{
Console.WriteLine(d.Name);
}
Dog dd = new Dog();
//dog ID is printed
foreach (Dog dog in dd.Each<Dog>())
{
Console.WriteLine(dog.ID);
}
}
}
public class Animal
{
public Animal()
{
Console.WriteLine("Animal constructued:" + this.ID);
}
private string _id { get; set; }
public string ID { get { return _id ?? (_id = Guid.NewGuid().ToString());} }
public bool IsAlive { get; set; }
}
public class Dog : Animal
{
public Dog() : base() { }
public string Name { get; set; }
}
public static class ObjectExtensions
{
public static IEnumerable<T> Each<T>(this object Source)
where T : class
{
T t = Source as T;
if (t == null)
yield break;
yield return t;
}
}
나는 개인적으로 깨끗한 방법을 선호합니다 :
Dog dog = animal as Dog;
if (dog != null)
{
// do stuff
}
if 문은 허용하지 않지만 for 루프는 허용합니다.
예 :
for (Dog dog = animal as Dog; dog != null; dog = null)
{
dog.Name;
...
}
작동 방식이 즉시 명확하지 않은 경우 프로세스에 대한 단계별 설명이 있습니다.
- 가변 개는 유형 개로 작성되며 Dog에 캐스트되는 가변 동물이 지정됩니다.
- 할당이 실패하면 dog가 널 (null)이므로 for 루프의 내용이 즉시 중단되므로 for 루프의 내용이 실행되지 않습니다.
- 할당이 성공하면 for 루프가
반복을 통해 실행됩니다 . - At the end of the iteration, the dog variable is assigned a value of null, which breaks out of the for loop.
using(Dog dog = animal as Dog)
{
if(dog != null)
{
dog.Name;
...
}
}
IDK if this helps anybody but you can always try to use a TryParse to assign your variable. Here is an example:
if (int.TryParse(Add(Value1, Value2).ToString(), out total))
{
Console.WriteLine("I was able to parse your value to: " + total);
} else
{
Console.WriteLine("Couldn't Parse Value");
}
Console.ReadLine();
}
static int Add(int value1, int value2)
{
return value1 + value2;
}
The total variable would be declared before your if statement.
I have just inlined the if statement to create a line of code that looks like what you are interested in. It just helps compress the code some and I found it to be more readable especially when nesting assignments:
var dog = animal as Dog; if (dog != null)
{
Console.WriteLine("Parent Dog Name = " + dog.name);
var purebred = dog.Puppy as Purebred; if (purebred != null)
{
Console.WriteLine("Purebred Puppy Name = " + purebred.Name);
}
var mutt = dog.Puppy as Mongrel; if (mutt != null)
{
Console.WriteLine("Mongrel Puppy Name = " + mutt.Name);
}
}
you can use something like that
//Declare variable bool temp= false;
if (previousRows.Count > 0 || (temp= GetAnyThing()))
{
}
참고URL : https://stackoverflow.com/questions/7113347/assignment-in-an-if-statement
'Programing' 카테고리의 다른 글
geoJSON 객체가 주어지면 d3에서지도 중앙에 (0) | 2020.06.27 |
---|---|
피보나치 시퀀스를 작성하는 방법? (0) | 2020.06.27 |
JavaScript에서 텍스트를 바꾸어 JavaScript에서 str_replace를 수행하려면 어떻게해야합니까? (0) | 2020.06.27 |
SVG에서 텍스트 요소의 수직 정렬 (0) | 2020.06.27 |
IntelliSense를 표시하는 Visual Studio 키보드 단축키 (0) | 2020.06.27 |